Tuesday, May 6, 2008

Python superclass and subclass interface consistency

Let Bar inherit from Foo and define x against both classes explicitly. Then define Foo.y, Foo.z equal to None but derive Bar.y, Bar.z as properties.

This doesn't work.

class Foo(object):
def __init__(self, x):
self.x = x
self.y = None
self.z = None

class Bar(Foo):
def __init__(self, x):
Foo.__init__(self, x)

@property
def y(self):
return self.x * 100

@property
def z(self):
return self.x * 1000

>>> foo = Foo(7)
>>> foo.x
7
>>> foo.y
>>> foo.z

>>> bar = Bar(8)
Traceback (most recent call last):
File "", line 1, in
File "test.py", line 9, in __init__
Foo.__init__(self, x)
File "test.py", line 4, in __init__
self.y = None
AttributeError: can't set attribute

But this does.

class Foo(object):
def __init__(self, x):
self.x = x

@property
def y(self):
return None

@property
def z(self):
return None

class Bar(Foo):
def __init__(self, x):
Foo.__init__(self, x)

@property
def y(self):
return self.x * 100

@property
def z(self):
return self.x * 1000

>>> foo = Foo(7)
>>> foo.x
7
>>> foo.y
>>> foo.z

>>> bar = Bar(8)
>>> bar.x
8
>>> bar.y
800
>>> bar.z
8000

A property in the subclass must implement as a property in the superclass. The pattern here ensures the interface consistency of both.

1 comment:

Jared Grubb said...

I dont see any inconsistency :) You cannot assign to a read-only property -- it's read-only!

So, you define Foo to have a property, but when __init__ gets run, it attempts to assign to it -- that's illegal!