Asked  7 Months ago    Answers:  5   Viewed   35 times

I would like to get all the instances of an object of a certain class.

For example:

class Foo {
}

$a = new Foo();
$b = new Foo();

$instances = get_instances_of_class('Foo');

$instances should be either array($a, $b) or array($b, $a) (order does not matter).

A plus is if the function would return instances which have a superclass of the requested class, though this isn't necessary.

One method I can think of is using a static class member variable which holds an array of instances. In the class's constructor and destructor, I would add or remove $this from the array. This is rather troublesome and error-prone if I have to do it on many classes.

 Answers

64

If you derive all your objects from a TrackableObject class, this class could be set up to handle such things (just be sure you call parent::__construct() and parent::__destruct() when overloading those in subclasses.

class TrackableObject
{
    protected static $_instances = array();

    public function __construct()
    {
        self::$_instances[] = $this;
    }

    public function __destruct()
    {
        unset(self::$_instances[array_search($this, self::$_instances, true)]);
    }

    /**
     * @param $includeSubclasses Optionally include subclasses in returned set
     * @returns array array of objects
     */
    public static function getInstances($includeSubclasses = false)
    {
        $return = array();
        foreach(self::$_instances as $instance) {
            if ($instance instanceof get_class($this)) {
                if ($includeSubclasses || (get_class($instance) === get_class($this)) {
                    $return[] = $instance;
                }
            }
        }
        return $return;
    }
}

The major issue with this is that no object would be automatically picked up by garbage collection (as a reference to it still exists within TrackableObject::$_instances), so __destruct() would need to be called manually to destroy said object. (Circular Reference Garbage Collection was added in PHP 5.3 and may present additional garbage collection opportunities)

Wednesday, March 31, 2021
 
dirigibleplum
answered 7 Months ago
68

You only need to use one $ when referencing an object's member variable using a string variable.

echo $this->$string;
Wednesday, March 31, 2021
 
Gordnfreeman
answered 7 Months ago
68

This is almost certainly a bad idea.

I think your time would be better spent creating a script that would create your class definitions for you, and not trying to do it at runtime.

Something with a command-line signature like:

./generate_classes_from_db <host> <database> [tables] [output dir]
Wednesday, March 31, 2021
 
Pupil
answered 7 Months ago
43

Yes. It's bad. It conflates the instance with the collection of instances.

Collections are one thing.

The instances which are collected are unrelated.

Also, class-level variables which get updated confuse some of us. Yes, we can eventually reason on what's going on, but the Standard Expectation™ is that state change applies to objects, not classes.


 class Foobar_Collection( dict ):
     def __init__( self, *arg, **kw ):
         super( Foobar_Collection, self ).__init__( *arg, **kw ):
     def foobar( self, *arg, **kw ):
         fb= Foobar( *arg, **kw )
         self[fb.name]= fb
         return fb

 class Foobar( object ):
     def __init__( self, name, something )
         self.name= name
         self.something= something

fc= Foobar_Collection()
fc.foobar( 'first', 42 )
fc.foobar( 'second', 77 ) 

for name in fc:
    print name, fc[name]

That's more typical.


In your example, the wait_for_deps is simply a method of the task collection, not the individual task. You don't need globals.

You need to refactor.

Friday, July 30, 2021
 
Kai
answered 3 Months ago
Kai
41

I have two ideas:

1/ Create a class array with all the instances static NSArray* instances;, register them when initializing, unregister when deallocating. The array should have only weak references, otherwise they will never be deallocated.

2/ NSNotification. All instances can wait for a notification and if you tap, you send the notification.

Thursday, August 19, 2021
 
Juned Ahsan
answered 2 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :