views:

139

answers:

3

I want to be able to create and unknown number of objects. I'm not sure if there is a better way to manage and reference them.

Lets use a standard OOP example... say every time a user enters a name for a pet in a text field and clicks a button a new pet object is created via the petFactory function.

function pet(name)
{
       this.name= name;
}

function petFactory(textFieldInput)
{
       var x = new pet(textFieldInput)
}

Since there's no way, that I know of (besides an eval function), to dynamically use a new, unique variable name for the pet every time petFactory is called, x is reassigned to a new object and the last pet is lost. What I've been doing is pushing the pet object onto an array as soon as it's initialized.

petArray.push(this);

So if I wanted the pet named 'mrFuzzyButtoms' I could loop through an indexed array until I found the object with the instance variable 'mrFuzzyButtoms'

for (n in petArray)
{
       if (petarray[n].name == 'mrFuzzyBottoms')
       {
               // Kill mrFuzzyBottoms
       }
}

or I could use an associative array...whatever...but the array is the only method I know for doing this. Besides using an eval function to create unique variable names from strings but some languages don't have an eval function (actionscript3) and then there is the security risk.

Is there a better way to do this?

Edit: Right now I'm working in Python, JavaScript and ActionScript.

+1  A: 

"I could use an associative array" Correct.

"the array is the only method I know for doing this."

Learn about "Mappings" or "Dictionaries" as soon as you can. You will find that it does exactly what you're asking for.

What language are you using? If you provide a specific language, we can provide specific links to the "Map" structure in that language.

S.Lott
Thanks a bunch. I added language tags.
j33r
+1  A: 

This what collection classes (lists, dictionaries/maps, sets) are for; to collect a number of instances. For the above case I would probably use a map (class name varies depending on language) from name to object.

Kathy Van Stone
In Python, this is called a "dict", in C# it is a Dictionary<keytype,valuetype>, or Hashtable if you don't want to use the generic type.
Paul McGuire
In AS3, you should probably use a plain-old-object, treated as an associative array (or a custom class that wraps an object). You can use a Dictionary as well; in your case it wouldn't make any difference.
fenomas
In Ruby it is Hash, in Java it is Map (with subclasses), and yes in javascript and actionscript you tend to use a generic object (you can also do so in Python, but it is not generally recommended).
Kathy Van Stone
A: 
#!/usr/bin/env python
"""Playing with pets.    

"""


class Pet(object):
    """A pet with a name."""
    def __init__(self, name):
        """Create a pet with a `name`.

        """
        self._name = name

    @property
    def name(self): # name is read-only
        return self._name

    def __repr__(self):
        """
        >>> eval(repr(self)) == self
        """
        klass = self.__class__.__name__
        return "%s('%s')" % (klass, self.name.replace("'", r"\'"))

    def __eq__(self, other):
        return repr(self) == repr(other)

    name2pet = {} # combined register of all pets

    @classmethod
    def get(cls, name):
        """Return a pet with `name`.

        Try to get the pet registered by `name` 
        otherwise register a new pet and return it
        """
        register = cls.name2pet
        try: return register[name]
        except KeyError:
            pet = register[name] = cls(name) # no duplicates allowed
            Pet.name2pet.setdefault(name, []).append(pet)
            return pet


class Cat(Pet):
    name2pet = {} # each class has its own registry


class Dog(Pet):
    name2pet = {}


def test():
    assert eval(repr(Cat("Teal'c"))) == Cat("Teal'c")

    pets = [Pet('a'), Cat('a'), Dog('a'), Cat.get('a'), Dog.get('a')]
    assert all(pet.name == 'a' for pet in pets)

    cat, dog = Cat.get('pet'), Dog.get('pet')
    assert repr(cat) == "Cat('pet')" and repr(dog) == "Dog('pet')"
    assert dog is not cat
    assert dog != cat    
    assert cat.name == dog.name

    assert all(v == [Cat(k), Dog(k)]
               for k, v in Pet.name2pet.items()), Pet.name2pet

    try: cat.name = "cat" # .name is read-only
    except AttributeError:
        pass

    try: assert 0
    except AssertionError:
        return "OK"
    raise AssertionError("Assertions must be enabled during the test")


if __name__=="__main__":
    print test()

pet.py

J.F. Sebastian
Thanks for the example. =) I will have to go over this in depth tonight.
j33r