Jump to content

Static class members & inheritance -- troubles


blaster999

Recommended Posts

Hello,

 

I am experiencing problems with static class members. For example, I have these classes:

abstract class ActiveRecord {
    protected static $db_fields = array();
    protected $DB_TABLE_NAME // the name of the table

    public function loadTableDef()
    {
        // here I load the table's filed list into self::$db_fields
    }
}

class Test1 extends ActiveRecord {
    protected $DB_TABLE_NAME = 'users';
}

class Test2 extends ActiveRecord {
    protected $DB_TABLE_NAME = 'lang_list';
}

$t1 = new Test1();
$t2 = new Test2();

$t1->loadTableDef();
$t2->loadTableDef();

 

And here's a surprise: both Test1 and Test2 share the same $db_fields (althoug these are different classes), which is not what I want. Is there a way to work around this issue?

Link to comment
Share on other sites

You miss my point.

 

If you mean "you don't understand what I'm trying to accomplish", you're absolutely right.

 

$t1 and $t2 are instances of different classes (both inherited from ActiveRecord).

 

Duh.

 

I want all instances of Test1 share the same value of $db_fields,

 

They do because they point to the same reference,

 

but that it would be different from the value of $db_fields in all the instances of Test2.

 

That's where you stop making sense. The static property is just that: static. ActiveRecord::$db_fields will be the same ActiveRecord::$db_fields, no matter what you do. It is confined to the class scope. Visibility is not the same as scope.

Link to comment
Share on other sites

I don't understand why Test1::$db_fields must be the same as Test2::$db_fields. And when I write "self::$db_fields", I mean it, not "parent::$db_fields".

 

Test1::$db_fields and Test2::$db_fields do not exist. Only ActiveRecord::$db_fields exists. Declaring something static confines it to the scope it was declared in.

Link to comment
Share on other sites

"confines" is the wrong word for it though, sorry about that. What I mean to say is that once you declare a variable or property static, the same reference will be used within that scope. New references will not be created. I don't know how else to explain it. If you don't understand variable referencing, there's a whole new topic to study right there.

Link to comment
Share on other sites

To add on -- remove the static keyword from before the variable, or define it separately in Test1 and Test2.  Obviously it's easier to remove the keyword.

 

What 448191 wanted to know is why you declared it static to begin with?  Was there a reason, or was completely at random?

Link to comment
Share on other sites

What 448191 wanted to know is why you declared it static to begin with?  Was there a reason, or was completely at random?

 

Well, I was under impression that PHP will create new static variables for each subclass (like other languages do IIRC). I was about to implement the ActiveRecord pattern, so each inherited class would work with a separate DB table, so it would make sense for all instances of, say, Test1 would share the same value for db_fields (because they all would work with the 'users' table). Each instance holds data from exactly 1 row from the table they are meant to work with.

 

BTW, I understand why PHP acts this way. I don't understand why was it designed to work this way. It's kind of counter-logical.

Link to comment
Share on other sites

I don't know how it works in other languages, but this same seems perfectly logical to me.  Static mean "does not change", so if a variable is static, why would it be different anywhere?  Creating new static variables for each subclass, to me, is illogical considering what static means.

 

Do other languages handle it differently?

Link to comment
Share on other sites

Do other languages handle it differently?

 

In fact, yes. That's what makes static variables much more useful than they are in PHP5. BTW, I am not the only one who has the same problem: see http://socket7.net/article/php-5-static-and-inheritance for example.

 

Maybe there is a way to emulate my expected behavior without code-duplication?

Link to comment
Share on other sites

BTW, I am not the only one who has the same problem: see http://socket7.net/article/php-5-static-and-inheritance for example.

 

That is not the same issue as you are describing. The man has three different static members, and only one method to retrieve them. The 'self' keyword in PHP is not dynamic, it doesn't change, i.e.: it is static.

 

What he (and you, I reckon) expect is a reference to the class at the bottom of the hierarchy (like the string returned by get_class()), what you get is a reference to the class the keyword was found in when parsing (like the string returned by __CLASS__). I'll agree with the guy that would be nice to have a build in mechanism to dynamically create a static reference to the latter. But there isn't.

 

BTW, I am not the only one who has the same

Maybe there is a way to emulate my expected behavior without code-duplication?

 

What you're trying to do is not possible. The very least you need is different declarations of $db_fields. You can write code that will dynamically reference to the different static members, but it's not pretty. The only effective way I've come across is using eval().

 

A better solution would be to simply use instance variables.

Link to comment
Share on other sites

Ok, I see... Could you please give me a hint on how to get the desired effect using eval?

 

The solution I see now is to use $db_fields[get_class($this)] instead of $db_fields. It's an ugly hack, and is not safe (each ActiveRecord subclass would have full access to static variables of all other subclasses).

Link to comment
Share on other sites

I've used something similar to the array solution you describe for lists of valid codes for 'code objects'. In such a case (when you have large amount of objects sharing the same reference) it might be worth the effort, but in general I don't really recommend it. Besides, the PHP engine internally doesn't make copies of variables until they actually change (Flyweigths, in a sense). So I'm not so sure it actually has any performance benefits. Just use non-static properties instead.

 

It does work though. You can prevent inappropriate access by checking the type in a getter.

 

abstract class Foo {
   
   private static $bars = array();

   protected function getBar(){
      return self::$bars[get_class($this)];
   }
   protected function setBar($value){
      self::$bars[get_class($this)] = $value;
   }
}

Link to comment
Share on other sites

Thanks! I think your solution might be apropriate.  The main reason I wanted to use static members was not to boost performance of PHP code, but rather to limit the number of DB queries (if I need to create, say, 10 instances of Test1, the query to determine the table fields will only be run once).

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.