Как инициализировать подкласс из метода суперкласса? - PullRequest
0 голосов
/ 07 октября 2019

В Интернете я читал, что питонным способом перегрузки конструкторов было создание методов класса. Поэтому я создал класс RectF, который можно инициализировать одним из двух способов.

class RectF:
    def __init__(self, x: float, y: float, w, h):
        self.x: float = x
        self.y: float = y
        self.width = w
        self.height = h

    @classmethod
    def from_tuples(cls, pos: tuple, size: tuple):
        return cls(pos[0], pos[1], size[0], size[1])

Конструктор init принимает аргумент для каждого поля, а метод from_tuples принимает два кортежа, содержащие координаты и размер. соответственно.

Однако, когда я иду инициализировать экземпляр подкласса, используя метод from_tuples, возникает исключение. Использование super().__init__() работает нормально.

class Entity(RectF):
    def __init__(self, pos: tuple, size: tuple, vel: tuple):
        super().__init__(pos[0], pos[1], size[0], size[1])

        # I would like to initialize the superclass using the from_tuples class method.
        # super().from_tuples(pos, size)
        # This throws the following exception: __init__() takes 4 positional arguments but 5 were given

        self.vel_x = vel[0]
        self.vel_y = vel[1]

Приведенный выше код является примером, и пока работает нормально. Но для удобства чтения и обслуживания;и в качестве наилучшей практики было бы полезно инициализировать объекты, используя наименьшее количество аргументов, особенно если они со временем становятся более сложными.

1 Ответ

2 голосов
/ 08 октября 2019

К моменту вызова __init__ объект уже построен, поэтому слишком поздно использовать from_tuples.

. Не используйте количество аргументов в качестве меры простоты. Вместо этого подумайте о том, какие методы можно использовать для реализации других. Если вы хотите, чтобы кортежи были основным строительным блоком прямоугольника, вы можете сделать это:

class RectF:
    def __init__(self, pos: tuple, size: tuple):
        self.x: float = pos[0]
        self.y: float = pos[1]
        self.width = size[0]
        self.height = size[1]

    # No good name for this method comes to mind
    @classmethod
    def from_separate_values(cls, x, y, w, h):
        return cls((x, y), (w, h))


class Entity(RectF):
    def __init__(self, pos: tuple, size: tuple, vel: tuple):
        super().__init__(pos, size)
        self.vel_x = vel[0]
        self.vel_y = vel[1]

    @classmethod
    def from_separate_values(cls, x, y, w, h, vx, vy):
        rv = super().from_separate_values(x, y, w, h)
        rv.vel_x = vx
        rv.vel_y = vy
        return rv
...