简体   繁体   English

实例化时在类外添加子类继承

[英]Adding subclass inheritance outside a class when instantiating

I want to add the inheritance of one or more classes to another class depending on specific requirements;我想根据具体要求将一个或多个类的继承添加到另一个类中; rather than creating multiple subclasses by hand, I want to be able to custom build them on the fly.我希望能够即时自定义构建它们,而不是手动创建多个子类。

For example, the primary class, that would inherit from the others, is Sandwich:例如,将从其他类继承的主要类是 Sandwich:

class Sandwich(object):
    def __init__(self):
        super(Sandwich, self).__init__()
        self.bread = "brown"
        self.amount = 2

The base classes would be:基类将是:

class Meat(object):
    def __init__(self):
        super(Meat, self).__init__()
        self.ham = False
        self.chicken = False
        self.beef = False

class Vegetables(object):
    def __init__(self):
        super(Vegetables, self).__init__()
        self.lettuce = False
        self.onion = False

class Vegan(Vegetables):
    def __init__(self, *args, **kwargs):
        super(Vegetables, self).__init__(*args, **kwargs)
        self.vegan_cheese = False

I want to create instances of these classes like this:我想像这样创建这些类的实例:

meat_sandwich = Sandwich(Meat)
veg_sandwich = Sandwich(Vegetables)
meat_and_veg_sandwich = Sandwich(Meat, Vegetables)
vegan_sandwich = Sandwich(Vegan)

I want to be able to access all variables and methods from these classes, and from the main class.我希望能够从这些类和主类访问所有变量和方法。

print(meat_sandwich.bread)
meat_sandwich.ham = True

I have found that you can assign a new class using __new__ , however I have only succeeded in replacing the main class, and not setting up multiple inheritance / subclassing:我发现您可以使用__new__分配一个新类,但是我只成功替换了主类,并没有设置多重继承/子类化:

    def __new__(cls, *args, **kwargs):
        """ Set to assign any given subclass """
        subcls = [i for i in args if isinstance(i, type)]

        if subcls:
            return super(Sandwich, cls).__new__(*subcls)

        else:
            return superSandwich, cls).__new__(cls)

Instead of using inheritance in my opinion it makes more sense to use composition here.在我看来,与其使用继承,不如在这里使用组合更有意义。

This will simplify the construction of the objects, and make it more flexible to change (such as adding new ingredients).这将简化对象的构造,并使其更灵活地更改(例如添加新成分)。

For example, each set of ingredient types could be a separate Enum :例如,每组成分类型都可以是一个单独的Enum

from enum import Enum

class Bread(Enum):
    WHITE = "white"
    WHOLE_WHEAT = "whole wheat"
    BROWN = "brown"

class Meat(Enum):
    HAM = "ham"
    CHICKEN = "chicken"
    BEEF = "beef"

class Vegetable(Enum):
    LETTUCE = "lettuce"
    ONION = "onion"

class Vegan(Enum):
    CHEESE = "vegan_cheese"

Now when defining the sandwich class you could do something like this:现在在定义三明治类时,您可以执行以下操作:

class Sandwich:
    def __init__(self, bread, ingredients=None):
        self.bread = bread
        self.ingredients = ingredients or []

To ask something like (as done in your example) if the sandwich contains ham, you could do:要询问(如您的示例中所做的)三明治是否包含火腿,您可以这样做:

>>> meat_sandwich = Sandwich(Bread.WHITE, [Meat.HAM])
>>> Meat.HAM in meat_sandwich.ingredients
True

To ask if the sandwich contains no meat, you could do:要询问三明治是否不含肉,您可以这样做:

>>> veg_sandwich = Sandwich(Bread.BROWN, [Vegetable.LETTUCE])
>>> all(not isinstance(i, Meat) for i in veg_sandwich.ingredients)
True

I've managed to get the results I was after, although I appreciate that I did not explain the problem very well, and suspect this might be something of a hack.我已经设法得到了我想要的结果,尽管我很感激我没有很好地解释这个问题,并且怀疑这可能是一种黑客行为。

At any rate, I hope this helps illustrate what it was I was trying to achieve, and I would be interested in hearing alternate approaches to this solution.无论如何,我希望这有助于说明我正在努力实现的目标,并且我有兴趣听到这个解决方案的替代方法。

meat_sandwich = type('meatSandwich_type', (Sandwich, Meat), dict())()
veg_sandwich = type('vegSandwich_type', (Sandwich, Vegetables), dict())()
meat_and_veg_sandwich = type('meatAndVegSandwich_type', (Sandwich, Meat, Vegetables), dict())()
vegan_sandwich = type('meatAndVegSandwich_type', (Sandwich, Vegan), dict())()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM