1
votes

Let's say I want to have a set of objects, each of which should have its own unique ID. Nothing fancy is needed, just a letter denoting which type of object it is, and a number denoting how many objects of these have been created. So for instance, a0, a1, b0, c0, c1, c2, c3, and so on.

Rather than setting global variables to keep track of how many of each object already exist, I want to do so with a class. Like so:

class uniqueIDGenerator
{
  private $numberAObjs;
  private $numberBObjs;
  private $numberCObjs;

  public function generateID ($type) {
    if($type === "A") {
      return 'a' . (int) $this->$numberAObjs++;
    } else if($type === "B") {
      return 'b' . (int) $this->$numberBObjs++;
    } else if($type === "C") {
        return 'c' . (int) $this->$numberCObjs++;
    }
  }
}

class obj
{
  private $id;

  function __construct($type) {
    $this->id = uniqueIDGenerator::generateID($type);
  }
}

The problem with this is that if uniqueIDGenerator is uninstantiated, its generateID function will always return the same values for each type (e.g. a0, b0, c0, etc.) because its private variables haven't actually been created in memory. At the same time, making it a property of obj won't work because then each time an obj is created, it will have its own instance of uniqueIDGenerator, so that will also always return a0, b0, c0, (assuming it's only called once in that object's methods) and so on.

The only option seems to be to make uniqueIDGenerator its own global instance so obj's constructor can reference it, but that seems poor coding practice. Is there any good, OOP way to do this that keeps all the objects separate and organized?

1
You need to store datas in files: either you open your file and write the ids in, either you use a database system (pgsql, mysql etc...). And you have to declare your method static - Pierre Emmanuel Lallemant
Thank you for your feedback, but this isn't for use with a webapp, it's just being written in PHP. This is a PHP script that will run once, read data from a file, and generate an output file in which each object generated needs to have its own unique identifier. - A. Duff
Can't you instanciate your uniqueIDGenerator once ? Ah I will write a proper answer ;) - Pierre Emmanuel Lallemant
Are the objects always of the same class? - Ja͢ck
You might try working with collections. They can keep track of the number of created objects. You might create a collection for each type you want to generate. The collection can iterate over the objects, return the number of objects etc. - busypeoples

1 Answers

1
votes

First you can modify object constructor:

class obj
{
  private $id;

  function __construct($type, $id) {
    $this->id = $id;
  }
}

...

$id_generator = new uniqueIDGenerator(); // instanciation of the generator

$obj1 = new obj(type, $id_generator->generateID($type));
$obj2 = new obj(type, $id_generator->generateID($type));
$obj3 = new obj(type, $id_generator->generateID($type));
...

In my projects, I would create a class named ObjectFactory:

    class ObjectFactory {
       private $id_generator;

       public function __construct($id_generator) {
          $this->id_generator = $id_generator;
       }

       public function create_object($type) {
          return new obj($this->id_generator->generateID($type));
       }
    }

...

$id_generator = new uniqueIDGenerator(); // instanciation of the generator
$obj_factory = new ObjectFactory($id_generator); 

$obj1 = obj_factory->create_object($type);
$obj2 = obj_factory->create_object($type);
$obj3 = obj_factory->create_object($type);

Finaly, to avoid the use of a global instance of this class, you can do a Singleton (adapted to your situation):

class uniqueIDGenerator
{
  private $numberAObjs;
  private $numberBObjs;
  private $numberCObjs;

  public static $instance = null;

  public function __construct() {
    $numberAObjs = 0;
    $numberBObjs = 0;
    $numberCObjs = 0;
  }

  public static function generateID($type) {
     if(!self::$instance)
        self::$instance = new uniqueIDGenerator();

     return self::$instance->generateID2($type);
  }

  private function generateID2 ($type) {
    if($type === "A") {
      return 'a' . (int) $this->numberAObjs++;
    } else if($type === "B") {
      return 'b' . (int) $this->numberBObjs++;
    } else if($type === "C") {
        return 'c' . (int) $this->numberCObjs++;
    }
  }
}

uniqueIDGenerator::generateID("A");