Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Replacing member objects with subclasses in Python

I have the following problem that I will attempt to illustrate with the following example.

class Brick():
    def __init__(self):
        self.weight = 1

class House():
    def __init__(self, number_bricks):
        self.bricks = [Brick() for i in range(number_bricks)]

    def get_weight(self):
        return reduce(lambda x,y: x+y, [brick.weight for brick in self.bricks])

But now suppose I create a new kind of Brick, StrongBrick, so that I make a house, a subclass StrongHouse, where StrongBrick plays exactly the same role in StrongHouse as Brick plays in House. How can I do this in a nice way (not just retyping all the class definitions)?

So the basic idea is, how can I change a class which is composed of some objects to the same class but composed of say a subclass of the original member objects?

Thanks very much for any help you can give me.

like image 687
user2428096 Avatar asked Sep 11 '26 21:09

user2428096


2 Answers

You could have a factory (a brickyard?) and pass that to House.__init__().

class Brick(object): pass

class StrongBrick(Brick): pass

class House(object):
    def __init__(self, brick_factory, num_bricks):
        self.bricks = [brick_factory() for i in range(num_bricks)]

house = House(Brick, 10000)
strong_house = House(StrongBrick, 10000)

As you can see, subclassing House isn't even necessary to be able to construct houses from different types of bricks.

like image 90
NPE Avatar answered Sep 13 '26 09:09

NPE


There are various ways to do this. You could make the relevant Brick class an attribute of the House class:

class House(object):
    brick_class = Brick

    def __init__(self, number_bricks):
        self.bricks = [self.brick_class() for i in range(number_bricks)]


class StrongHouse(House):
    brick_class = StrongBrick

Or, you could pass in the Brick class you want to use when constructing the House:

class House(object):

    def __init__(self, brick_class, number_bricks):
        self.bricks = [brick_class() for i in range(number_bricks)]
like image 37
Daniel Roseman Avatar answered Sep 13 '26 10:09

Daniel Roseman



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!