Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Override static method (or workaround)

4 views
Skip to first unread message

matt

unread,
Aug 24, 2010, 3:18:02 PM8/24/10
to
I'm tried to figure out the best way to implement this concept.
Basically, I've got the following:

abstract class DataObject
{
protected function create($data, &$insert_id)
{
// do database insert
// set last insert id
}
}

class Table extends DataObject
{
public function create($data)
{
// custom field validation
parent::create($data, $id);
return new Table($id);
}
}

Table::create($data) raises the following E_STRICT error:

Non-static method Table::create() should not be called statically,
assuming $this from incompatible context

Of course, I can't declare either function as static, and I'm hoping
that I don't have to rename one of the functions, as that could
potentially break a lot of legacy code. Is there any way to do this
and pass E_STRICT reporting?

Jerry Stuckle

unread,
Aug 24, 2010, 4:47:03 PM8/24/10
to

Nope. The error is correct - these are non-static functions, and you
are calling create() statically.

The problem is non-static member functions expect a $this reference, and
you don't have one when you call them statically like this. If they are
static functions, you need to make them static functions. Of course,
you won't have access to any non-static member variables or functions -
but then you don't if you don't have a $this reference, anyway.

--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
jstu...@attglobal.net
==================

Michel Bartz

unread,
Aug 24, 2010, 5:42:26 PM8/24/10
to
You can hack your way around with __callStatic :

<?php
abstract class SomeClass
{
protected function test() {
echo "test 42";
}
}

class AnotherClass extends SomeClass {

private static $_instance = null;

public static function __callStatic($name, $args) {
if(is_null($_instance)) {
$class = get_called_class();
self::$_instance = new $class();
}
if(method_exists(self::$_instance, $name)) {
echo 1;
call_user_func_array(array(self::$_instance, $name), $args);
}
}

public function test() {
parent::test();
return " 43";
}
}

echo AnotherClass::test();
//output test 42 43

It nasty, but it does the job. Basically it will hold a Singleton
instance of your object for any static call you want to make to your
non-static functions.

Helmut Chang

unread,
Aug 24, 2010, 5:43:04 PM8/24/10
to
matt schrieb:

> abstract class DataObject
> {
> protected function create($data, &$insert_id)
> {
> // do database insert
> // set last insert id
> }
> }
>
> class Table extends DataObject
> {
> public function create($data)
> {
> // custom field validation
> parent::create($data, $id);
> return new Table($id);
> }
> }

Your subject is somehow misleading: Neither is one of the methods
static, nor do you override a method here. Overriding a method means:
you reimplement a method from a base type with the same signature and it
will be called instead of the overridden method. That's not the case here.

> Table::create($data) raises the following E_STRICT error:
>
> Non-static method Table::create() should not be called statically,
> assuming $this from incompatible context
>

> Of course, I can't declare either function as static,...

Why not? If you want to call theam statically, you must declare them
statically. At least for Table::create(), I can't see, why you cannot
make it statically. And for DataObject::create(): If this method uses
instance context like $this, it wouldn't work this way. Then you must
find a way to call the method for example from the Table's constructor.
But I think, I haven't got the concept: You do an insert of some data,
getting an ID from it. Then you create a new Table instance with this
ID. And what happens with the $data? Is it not needed in the table instance?

> and I'm hoping
> that I don't have to rename one of the functions, as that could
> potentially break a lot of legacy code.

That's bad. Because, as I've written already: you don't override
anything here. You have a method in DataObject and you have another
method with the same name in Table. But Table::create() will never be
called *instead* of DataObject::create(). It just uses it as a common
helper.

> Is there any way to do this
> and pass E_STRICT reporting?

Don't think so. And even if you would manage this, the next E_STRICT
would be:

PHP Strict Standards: Declaration of Table::create() should be
compatible with that of DataObject::create() in...

Just tested with PHP 5.3.2.

And both E_STRICT warnings indicate, that your design is wrong.

--- news://freenews.netfront.net/ - complaints: ne...@netfront.net ---

Michael Fesser

unread,
Aug 24, 2010, 5:53:22 PM8/24/10
to
.oO(matt)

>I'm tried to figure out the best way to implement this concept.
>Basically, I've got the following:
>
>abstract class DataObject
>{
> protected function create($data, &$insert_id)
> {
> // do database insert
> // set last insert id
> }
>}
>
>class Table extends DataObject
>{
> public function create($data)
> {
> // custom field validation
> parent::create($data, $id);
> return new Table($id);
> }
>}

Since you know the name of the class and the base class, why not do it
like this:

class Table extends DataObject
{
public static function create($data)
{
// custom field validation
DataObject::create($data, $id);
return new Table($id);
}
}

Micha

Gordon

unread,
Aug 25, 2010, 7:15:10 AM8/25/10
to

You haven't declared your functions as static, so you can't call them
as if they were static functions.

Either declare your functions as static (static public function foo
()), or call them as instance functions ($this -> foo ()).

matt

unread,
Aug 25, 2010, 8:39:06 AM8/25/10
to

Jerry, thanks for the reply, but I'm not confused by PHP's behavior or
the error message here. I understand the purpose of static and non-
static methods. The problem is that it is invalid to override a
static method (as I understand it), even though in practice, that's
what the application demands.

matt

unread,
Aug 25, 2010, 8:55:56 AM8/25/10
to
On Aug 24, 5:43 pm, Helmut Chang <use...@helmutchang.at> wrote:
> matt schrieb:
>
>
>
> > abstract class DataObject
> > {
> >   protected function create($data, &$insert_id)
> >   {
> >     // do database insert
> >     // set last insert id
> >   }
> > }
>
> > class Table extends DataObject
> > {
> >   public function create($data)
> >   {
> >     // custom field validation
> >     parent::create($data, $id);
> >     return new Table($id);
> >   }
> > }
>
> Your subject is somehow misleading: Neither is one of the methods
> static, nor do you override a method here. Overriding a method means:
> you reimplement a method from a base type with the same signature and it
> will be called instead of the overridden method. That's not the case here.

Sorry, didn't mean to mislead. No, they are not static functions, but
they SHOULD be. I recognize that the methods don't have the same
signature, but in a programming language that doesn't support method
overloading, how is that not, in effect, overriding a method?

> > Table::create($data) raises the following E_STRICT error:
>
> > Non-static method Table::create() should not be called statically,
> > assuming $this from incompatible context
>
> > Of course, I can't declare either function as static,...
>
> Why not? If you want to call theam statically, you must declare them
> statically. At least for Table::create(), I can't see, why you cannot
> make it statically. And for DataObject::create(): If this method uses
> instance context like $this, it wouldn't work this way. Then you must
> find a way to call the method for example from the Table's constructor.
> But I think, I haven't got the concept: You do an insert of some data,
> getting an ID from it. Then you create a new Table instance with this
> ID. And what happens with the $data? Is it not needed in the table instance?

I just realized something in testing this out...I was getting the
following error:

64: Cannot make non static method DataObject::create() static in class
Table2

After declaring both methods as static. I'm doing some automatic unit
testing on a large code base here and I hadn't noticed that the error
message was referring to a different table when I originally posted.
I was under the impression that I couldn't override a static method
(think I read that somewhere). Looks like it's actually okay, and now
is moving on to the next inherited class with a valid error.

> > and I'm hoping
> > that I don't have to rename one of the functions, as that could
> > potentially break a lot of legacy code.
>
> That's bad. Because, as I've written already: you don't override
> anything here. You have a method in DataObject and you have another
> method with the same name in Table. But Table::create() will never be
> called *instead* of DataObject::create(). It just uses it as a common
> helper.
>
> > Is there any way to do this
> > and pass E_STRICT reporting?
>
> Don't think so. And even if you would manage this, the next E_STRICT
> would be:
>
> PHP Strict Standards:  Declaration of Table::create() should be
> compatible with that of DataObject::create() in...

I'm not sure what you did to generate that error...

> Just tested with PHP 5.3.2.
>
> And both E_STRICT warnings indicate, that your design is wrong.

That's a loaded statement. How would you design it differently?

Jerry Stuckle

unread,
Aug 25, 2010, 11:22:18 AM8/25/10
to

Where do you see that it's illegal to override a static function?

Helmut Chang

unread,
Aug 25, 2010, 11:43:37 AM8/25/10
to
matt schrieb:

> Sorry, didn't mean to mislead.

Also sorry! Didn't want to attack you. Just wanted to make it clear,
that I think you have a misconcept:

> ...I recognize that the methods don't have the same


> signature, but in a programming language that doesn't support method
> overloading, how is that not, in effect, overriding a method?

IMO because the overriding method is not called *automatically* instead
of the overridden method. In addition, you cannot not call on overridden
method from outside the class where it was overridden. But you can call
each overload of a method, everywhere where it's accessible.

In those languages, I know, that suport method overloading, you also
have to override a specific overload with exactly the same signature.
That does not mean, you override all overloads of this method from the
base class.

And as you see with my example written, PHP *thinks* the same, in
raising an E_STRICT warning.

You tried to overload, not to override a method (through inheritance) in
a language that does not support it.

> I was under the impression that I couldn't override a static method
> (think I read that somewhere).

Yes, if you see "overriding" as described above: you cannot (or could
not until PHP 5.3). Consider the following:

class A {
public function myMethod() {
$this->overridable();
}

protected function overridable() {

}
}

class B {
protected function overridable() {

}
}

$b = new B();
$b->myMethod();

Here, with instance methods, B::overridable() is called. And that's,
what overriding means in my understanding.

Same with static methods:

class A {
public static function myMethod() {
self::overridable();
}

protected static function overridable() {

}
}

class B {
protected static function overridable() {

}
}

B::myMethod();

Here A::overridable() is called. Because myMethod() is a class (not an
instance) method of A. And the method is called in the context of class
A. And so calls the class method overridable() of A, not B. So to be
exact: you cannot override a static method, like an instance method.

Since PHP 5.3 it's possible in using static instead of self.

>>
>> PHP Strict Standards: Declaration of Table::create() should be
>> compatible with that of DataObject::create() in...
>
> I'm not sure what you did to generate that error...

Following simple script:

<?php
abstract class A {
protected function foo() {

}

protected static function bar() {

}
}

class B extends A {
public function foo($bar) {

}

public static function bar($bar) {

}
}

$b = new B();
$b->foo('bar');
B::bar('bar');
?>

>> And both E_STRICT warnings indicate, that your design is wrong.
>
> That's a loaded statement. How would you design it differently?

I'm not sure now, which of you problems still remain:

If you still can't make those methods statically, you must find a way,
not to call them statically. A method should only be defined and called
statically, if it does not depend on the state of an instance. Your
Table::create() method seemed to me such a method. But I'm not sure
about your DataObject::create() method.

The other design problem is the name, as you can see: PHP will tell you,
that you don't override a method correct. And I agree with it ;). I see
DataObject::create() as a helper method for the create()-Methods of
conrete DataObject implementations like your Table class. So you
shouldn't have called it create(). Or you shouldn't have called your
method in Table create(). That's what I meant with "wrong" design. I
can't give you a solution, if you can't rename one of your methods...

matt

unread,
Aug 25, 2010, 11:56:02 AM8/25/10
to

Like I responded to Helmut, I believe I read it somewhere, and I was
mis-reading an error that was falsely confirming my bad assumption!
Sounds like this may have been true before 5.3? Anyway, I think I've
got it licked now.

0 new messages