Viewed   76 times

I have this code:

private static $dates = array(
  'start' => mktime( 0,  0,  0,  7, 30, 2009),  // Start date
  'end'   => mktime( 0,  0,  0,  8,  2, 2009),  // End date
  'close' => mktime(23, 59, 59,  7, 20, 2009),  // Date when registration closes
  'early' => mktime( 0,  0,  0,  3, 19, 2009),  // Date when early bird discount ends
);

Which gives me the following error:

Parse error: syntax error, unexpected '(', expecting ')' in /home/user/Sites/site/registration/inc/registration.class.inc on line 19

So, I guess I am doing something wrong... but how can I do this if not like that? If I change the mktime stuff with regular strings, it works. So I know that I can do it sort of like that..

Anyone have some pointers?

 Answers

4

PHP can't parse non-trivial expressions in initializers.

I prefer to work around this by adding code right after definition of the class:

class Foo {
  static $bar;
}
Foo::$bar = array(…);

or

class Foo {
  private static $bar;
  static function init()
  {
    self::$bar = array(…);
  }
}
Foo::init();

PHP 5.6 can handle some expressions now.

/* For Abstract classes */
abstract class Foo{
    private static function bar(){
        static $bar = null;
        if ($bar == null)
            bar = array(...);
        return $bar;
    }
    /* use where necessary */
    self::bar();
}
Saturday, October 15, 2022
1

Because you are using PHP 5.3, you can use late static binding to resolve the static call to the right class at runtime.

class base_class {

    public function doSomethingWithReference(){
        static::$reference->doSomething();
    }

}

class extended_class extends base_class{

    protected static $reference;

    public function __construct($ref){
        static::$reference = $ref;
    }

}

Big fat reminder: That one extended_class::$reference is going to be shared amongst all of the extended_class instances. If that is not what you intend, this is not going to work.

You seem to actually be worried about memory or resource use. In PHP, all objects are passed by reference. This means that passing an object as an argument, or creating a copy of it, etc, does not consume extra memory. If you need to reference an object in a number of other objects, doing so will not consume extra memory.


If I had extended_class and another identical class (say extended_class1) would they share the reference as well? or would all extended_class' instances share one reference, while all extended_class1' instances would share another (the ideal case)?

It looks like the sharing is based on where the static variable is defined. Two examples, both from the PHP interactive prompt:

php > class Shared { public $me; public function __construct($me) { $this->me = $me; } }
php > class Base { protected static $ref; public function foo() { echo static::$ref->me, "n"; } }
php > class Inherit_1 extends Base { public function __construct($ref) { static::$ref = $ref; } }
php > class Inherit_2 extends Base { public function __construct($ref) { static::$ref = $ref; } }
php > class Inherit_3 extends Inherit_1 {}
php > $shared_1 = new Shared(1)
php > ;
php > $shared_2 = new Shared(2);
php > $shared_3 = new Shared(3);
php >
php > $in_1 = new Inherit_1($shared_1);
php > $in_2 = new Inherit_2($shared_2);
php > $in_3 = new Inherit_3($shared_3);
php >
php > $in_1->foo();
3
php > $in_2->foo();
3
php > $in_3->foo();
3

In this case, because the reference lives in the base class, everyone sees the same one. I suppose this makes some sort of sense.

What happens when we declare the reference with each child class.. most of the time?

php > class Shared { public $me; public function __construct($me) { $this->me = $me; } }
php > class Base { public function foo() { echo static::$ref->me, "n"; } }
php > class Inherit_1 extends Base { protected static $ref; public function __construct($ref) { static::$ref = $ref; } }
php > class Inherit_2 extends Base { protected static $ref; public function __construct($ref) { static::$ref = $ref; } }
php > class Inherit_3 extends Inherit_1 {}
php > class Inherit_4 extends Inherit_1 { protected static $ref; }
php > $shared_1 = new Shared(1);
php > $shared_2 = new Shared(2);
php > $shared_3 = new Shared(3);
php > $shared_4 = new Shared(4);
php > $in_1 = new Inherit_1($shared_1);
php > $in_2 = new Inherit_2($shared_2);
php > $in_3 = new Inherit_3($shared_3);
php > $in_4 = new Inherit_4($shared_4);
php > $in_1->foo();
3
php > $in_2->foo();
2
php > $in_3->foo();
3
php > $in_4->foo();
4

Because 3 inherited from 1 without declaring it's own static property, it inherited 1's. When we set 3's to Shared(3), it overwrote 1's existing Shared(1).

Conclusion: For this to work, the property needs to be declared in every class that needs the single unique reference. Note that this code is valid as of 5.4.x.

Tuesday, September 27, 2022
 
walt_w
 
1

You can't define a static member variable more than once. If you put variable definitions into a header, it is going to be defined in each translation unit where the header is included. Since the include guards are only affecting the compilation of one translation unit, they won't help, either.

However, you can define static member functions! Now, at first sight that may not look as if it could help except, of course, that function can have local static variable and returning a reference to one of these behaves nearly like a static member variable:

static std::string& bstring() { static std::string rc{"."}; return rc; }

The local static variable will be initialized the first time this function is called. That is, the construction is delayed until the function is accessed the first time. Of course, if you use this function to initialize other global objects it may also make sure that the object is constructed in time. If you use multiple threads this may look like a potential data race but it isn't (unless you use C++03): the initialization of the function local static variable is thread-safe.

Sunday, December 4, 2022
3

I also posted this question on scala users google group and Bill Venners one of the authors of "Programming in scala" reply had some insights.

Take a look at this: https://groups.google.com/d/msg/scala-user/5jZZrJADbsc/6vZJgi42TIMJ and https://groups.google.com/d/msg/scala-user/5jZZrJADbsc/oTrLFtwGjpEJ

Here is an excerpt:

I think one goal was simply to be simpler, by having every value be an object, every operation a method call. Java's statics and primitives are special cases, which makes the language more "complicated" in some sense.

But another big one I think is to have something you can map Java's statics to in Scala (because Scala needed some construct that mapped to Java's statics for interop), but that benefits from OO inheritance/polymorphism. Singleton objects are real objects. They can extend a superclass or mix in traits and be passed around as such, yet they are also "static" in nature. That turns out to be very handy in practice.

Also take a look at this interview with Martin Odersky (scroll down to Object-oriented innovations in Scala section) http://www.artima.com/scalazine/articles/goals_of_scala.html

Here is an excerpt:

First, we wanted to be a pure object-oriented language, where every value is an object, every operation is a method call, and every variable is a member of some object. So we didn't want statics, but we needed something to replace them, so we created the construct of singleton objects. But even singleton objects are still global structures. So the challenge was to use them as little as possible, because when you have a global structure you can't change it anymore. You can't instantiate it. It's very hard to test. It's very hard to modify it in any way.

To Summarize:

From a functional programming perspective static members are generally considered bad (see this post by Gilad Bracha - the father of java generics. It mainly has to do with side effects because of global state). But scala had to find a way to be interoperable with Java (so it had to support statics) and to minimize (although not totally avoid) global states that is created because of statics, scala decided to isolate them into companion objects.

Companion objects also have the benefit of being extensible, ie. take advantage of inheritance and mixin composition (separate from emulating static functionality for interop).

Tuesday, December 27, 2022
 
5

Partial specialization of members (whether they're functions or static data) are not allowed without partial specialization of enclosing class template itself.

That is, you have to specialize the class template also. So the following should work:

//partial specialization of class template
template <bool B>
struct from<true, B> {
    const static std::string value; 
};

//now you can do this!    
template <bool B>
const std::string from<true, B>::value = ""

Also, this will not compile (have you tried compiling this?):

// full specialization - works (SORRY, IT WILL NOT WORK!)
const std::string from<false, true>::value = "";  //this should be an error

You've to write this:

// full specialization 
template<>   //<---- this is important!
const std::string from<false, true>::value = ""
Wednesday, August 3, 2022
 
Only authorized users can answer the search term. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :