Классы Python: различия между наследованием и созданием экземпляра родительского класса внутри дочернего (состав класса)

#python #class #inheritance #instance #parent-child

Вопрос:

У меня есть следующая проблема:

У меня есть класс A, в котором хранится только большое количество переменных; затем у меня есть 3 класса ,B, C, D, которые наследуют A для определения более сложных объектов (разных в каждом из 3 классов), которые зависят от набора переменных, определенных в A. Наконец, существует класс E, который должен наследовать только один между B, C, D.

Поскольку мне нужна гибкость, чтобы каждый раз выбирать класс для включения в E, мне не нужно фиксированное имя родителя в качестве аргумента E. Для этого вместо наследования класса я создаю экземпляр класса в __init__() методе (чтобы также получить доступ ко всем родительским методам и атрибутам); Я сообщаю ниже 2 разных способа лучше выразить идею. Мой вопрос таков:

Есть ли какие-то минусы в том, чтобы идти моим путем, или, в более общем плане, в чем различия между этими 2 подходами?

 class E(D):
    def __init__(self, argsE, argsPar):
        super().__init__(self, argsPar)
    ...
 

(в приведенном выше примере я должен указать родительский класс, который я хочу ввести, а не исправлять)

 class E:
    def __init__(self, parent, argsE, argsPar):
        if(parent=='B')
            self.parent = B(argsPar)
        if(parent=='C')
            self.parent = C(argsPar) 
        if(parent=='D')
            self.parent = D(argsPar)
      
    ...
 

Комментарии:

1. В соответствии с некоторыми стандартными шаблонами ООП: Почему бы вам не использовать три класса E(D) , F(C) , G(D) ? Почему бы вам не передать уже существующий экземпляр любого B из них , C , D E кому ? Используете ли вы наследование, потому что это на самом деле подтипы ( E «является» A ) или просто повторное использование кода?

2. Привет, Мистермияги, спасибо за комментарий; не уверен, что я правильно его понял. Вы предлагаете создать отдельную копию E для каждого возможного родителя? Я использую наследование от A до B , C , D для повторного использования кода (то же самое для E )

3. Я не совсем понимаю вашу проблему, поэтому хотел бы воздержаться от каких-либо предложений. Однако простое создание нового класса для каждого варианта кажется простым, поэтому, чтобы понять вашу проблему, я хотел бы знать, есть ли у вас причина не делать эту простую вещь. Мое личное предчувствие состоит в том, что вам вообще не следует использовать наследование, а только композицию.

Ответ №1:

Поскольку мне нужна гибкость, чтобы каждый раз выбирать класс для включения в E, мне не нужно фиксированное имя родителя в качестве аргумента E.

Затем просто используйте type для динамического создания класса, рассмотрим следующий пример

 class A:
    pass
class B:
    pass
choice = input("Shall C inherit A xor B?")
if choice == "A":
    C = type("C", (A,), {})
elif choice == "B":
    C = type("C", (B,), {})
else:
    exit()
print(issubclass(C,A))  # True if choice was A else False
print(issubclass(C,B))  # True if choice was B else False
 

Третий аргумент для ввода должен быть

словарь содержит определения атрибутов и методов для тела класса

В приведенном выше примере для краткости использовался пустой dict ,