Creating new instances of subclasses.

J. Cliff Dyer jcd at sdf.lonestar.org
Fri Jan 9 16:50:15 CET 2009


Thanks for the solutions everyone!  I'm not sure which I'll end up
using, but I think I've got a better grasp of the problem now.  

Cool stuff.

Cheers,
Cliff

On Thu, 2009-01-08 at 06:52 -0800, Paul McGuire wrote:
> On Jan 7, 12:00 pm, Paul McGuire <pt... at austin.rr.com> wrote:
> > On Jan 7, 10:38 am, "J. Cliff Dyer" <j... at unc.edu> wrote:
> >
> > > I want to be able to create an object of a certain subclass, depending
> > > on the argument given to the class constructor.
> >
> > > I have three fields, and one might need to be a StringField, one an
> > > IntegerField, and the last a ListField.  But I'd like my class to
> > > delegate to the proper subclass automatically, so I can just do:
> >
> > > >>> f1 = Field('abc')
> > > >>> f2 = Field('123')
> > > >>> f3 = Field('D,E,F')
> >
> > O-O is not always the solution to every problem.  Since inheritance is
> > getting in your way, try using a class-level factory method.  Instead
> > of using the Field constructor, use a staticmethod of Field, something
> > like:
> >
> > @staticmethod
> > def make_Field(a)
> >     if is_list(a):
> >         return ListField(a)
> >     elif is_integer(a):
> >         return IntegerField(a)
> >     else:
> >         return StringField(a)
> >
> > and then get rid of all those __new__ methods, too.
> >
> > -- Paul
> 
> After looking this over a bit more, I decided I didn't like make_Field
> having to know the criteria for creating the different subclasses, but
> wanted to put the smarts into the subclasses themselves.  Here is an
> excerpt that shows this working:
> 
> class Field(object):
>     def __init__(self, input):
>         super(Field, self).__init__(input)
>         self.data = input
> 
>     @staticmethod
>     def make_Field(a):
>         subs = (ListField, IntegerField, StringField)
>         ret = None
>         for cls in subs:
>             try:
>                 ret = cls(a)
>             except TypeError:
>                 continue
>             else:
>                 break
>         return ret
> 
> class IntegerField(Field):
>     def __new__(cls, a):
>         if not is_integer(a):
>             raise TypeError()
>         return Field.__new__(cls, a)
> 
> ...
> ListField has a similar __new__ method, and StringField just creates
> the object, with no validation.
> 
> make_Field still has to know what order to list the subclasses in
> (StringField is the most permissive, and so must come last in the list
> of subclasses), but the specific type tests are moved into the
> subclasses, which is a more appropriate place I think.
> 
> -- Paul
> --
> http://mail.python.org/mailman/listinfo/python-list
> 




More information about the Python-list mailing list