Взаимозависимости классов Python - PullRequest
0 голосов
/ 08 декабря 2018

У меня есть класс Python, который служит базовым классом для дальнейших подклассов.Он содержит методы, которые должны действовать на все подклассы одинаково, например, я хочу поместить его в базовый класс.Проблема в том, что этот метод должен возвращать новый экземпляр подкласса.Но так как базовый класс находится перед определением подкласса, я не могу создать новый экземпляр подкласса, так как он не известен в области действия базового класса:

class Base:
  def __init__(self, value):
    self.value = value

  def convert_child_classes(self, newclass):
    newvalue = MakeUsableInNewclass(self.value)
    newattr = MakeUsableInNewclass(self.subclassattr)
    return newclass(newattr, newvalue)


class Child1(Base):
  def __init__(self, subclassattr, value)
    super(Child, self).__init__(value)
    self.subclassattr = subclassattr

  def MethodForSubClassAttr(self):
    ...do sth with self.subclassattr...


class Child2(Base):
  def __init__(self, subclassattr, value)
    super(Child, self).__init__(value)
    self.subclassattr = subclassattr

  def SomeOtherSubClassAttrMethod(self):
    ...do sth that is related to this class attr...

I, если у меня естьэкземпляр Child1 Я хочу иметь возможность сделать некоторые вещи с его данными, а затем вернуть экземпляр Child2 с новыми значениями при вызове convert_child_classes (Child2):

A = Child1('someattr', 5)
B = A.convert_child_classes(Child2)

теперь B должен быть экземпляромChild2 со значением, которое было вычислено из Child1.Но поскольку базовый класс теперь знает, что такое Child1 или Child2, он не может инициировать новый класс.

Ответы [ 2 ]

0 голосов
/ 08 декабря 2018

У меня есть ваша проблема:
1. На самом деле вы используете Child в super, и это неправильно, так как это должно быть имя класса, с которым вы работаете, в данном случае Child1 или Child2.
2. Я бы добавил Base в качестве абстрактного класса, чтобы гарантировать, что он не будет создан (как я понял из вашего вопроса, это так).
3. Поскольку метод MakeUsableInNewClass является обязательным для реализации, я бы добавил как abstractmethod, чтобы обеспечить реализацию на дочерних.

Таким образом, правильный код будет:

from abc import ABC, abstractmethod
class Base(ABC):
    def __init__(self, value):
        self.value = value

    def convert_child_classes(self, newclass):
        newvalue, newattr = self.MakeUsableInNewclass()
        return newclass(newattr, newvalue)

    @abstractmethod
    def MakeUsableInNewclass(): pass

class Child1(Base):
    def __init__(self, subclassattr, value):
        super(Child1, self).__init__(value)
        self.subclassattr = subclassattr

    def MakeUsableInNewclass(self):
        newvalue = self.value #do operations
        newattr = self.subclassattr #do operations
        return newvalue, newattr

class Child2(Base):
    def __init__(self, subclassattr, value):
        super(Child2, self).__init__(value)
        self.subclassattr = subclassattr

    def MakeUsableInNewclass(self):
        newvalue = self.value #do operations
        newattr = self.subclassattr #do operations
        return newvalue, newattr
0 голосов
/ 08 декабря 2018

Что-то вроде этого должно работать (не проверено):

class Measurement:

    @classmethod
    def from_other(cls, other):
        base = other.convert_to_base_unit()
        converted = cls.base_to_unit(base)
        return cls(converted)

    @classmethod
    def base_to_unit(cls, value):
        # Let the subclass implement this
        raise NotImplementedError

    def convert_to_base_unit(self):
        # Let the subclass implement this
        raise NotImplementedError

Реализованный таким образом, базовый класс не должен ничего знать о подклассах.Базовый класс предоставляет метод шаблона (from_other), а подклассы обеспечивают реализацию.

...