Подкласс Objective C initWithSuperClass - PullRequest
0 голосов
/ 29 июня 2009

Общий суперкласс прямоугольника и круга - это форма.

Если я инициализирую некоторые фигуры, каков хороший способ позже преобразовать фигуру в круг и сохранить те же свойства, заданные, пока она была фигурой? Должен ли я реализовать initWithShape в подклассах, который выглядит примерно так?

- (id) initWithShape:(Shape*)aShape {
    self = (id) aShape;

    // set circle or rectangle specific values

    return self;
}

У кого-нибудь есть пример, на который я могу взглянуть?

Ответы [ 4 ]

2 голосов
/ 29 июня 2009

Не делай то, что ты только что сделал. Подумайте о том, что происходит, когда вы делаете это:

Shape *shape = ...;
Rectangle *rect = [[Rectangle alloc] initWithShape:shape];

Во второй строке выделяется экземпляр Rectangle. Затем возвращаемое значение для initWithShape снова равно shape, поэтому новое Rectangle, которое мы только что выделили, было пропущено!

Приведение к id также не требуется - любой объект Objective-C может быть неявно приведен к id.

Мне не совсем понятно, что вы пытаетесь сделать. Возможно, если бы вы уточнили свой вопрос, я мог бы сказать вам, что вы должны делать.

1 голос
/ 29 июня 2009

Вы не можете изменить объект после того, как он был создан, кроме как путем его освобождения и создания нового (что вы можете сделать в методе init, и на самом деле это довольно часто делается для синглетонов или кластеров классов), но это не совсем то, что вы ищете.

Дайте существующему объекту Shape с некоторыми свойствами, ваша единственная реальная возможность - создать новый объект на основе свойств формы. Что-то вроде:

В Shape.m:

- (id) initWithShape:(Shape*)aShape {
    self = [super init];
    if (self != nil) {
        // copy general properties
        _x = aShape.x;
        _y = aShape.y;
        _color = [aShape.color copy];
    }
    return self;
}

In Circle.m:

- (id) initWithShape:(Shape*)aShape {
    self = [super initWithShale:aShape];
    if (self != nil) {
        // base properties on the class of the shape
        if ( [aShape isKindOfClass:[Oval class]] ) {
            // average the short and long diameter to a radius
            _radius = ([(Oval*)aShape shortDiameter] + [(Oval*)aShape longDiameter])/4;
        } else {
            // or use generic Shape methods
            _radius = aShape.size / 2;
        }
    }
    return self;
}
0 голосов
/ 29 июня 2009

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

// for rectangle
- (void) takePropertiesFrom:(Shape *) aShape
{
    if ([aShape isKindOfClass:[Circle class]])
    {
        float radius = [aShape radius];
        [self setWidth:radius * 2];
        [self setHeight:radius * 2];
    }
    else
    {
        [self setWidth:[aShape width]];
        [self setHeight:[aShape height]];
    }
}

// for circle
- (void) takePropertiesFrom:(Shape *) aShape
{
    if ([aShape isKindOfClass:[Rectangle class]])
        [self setRadius:[aShape width] / 2];
    else
        [self setRadius:[aShape radius]];
}

Очевидно, что вы захотите настроить открытый интерфейс для Shape, который предоставляет основные свойства формы, такие как высота и ширина, и тогда вам не нужно будет жестко кодировать кражу свойств на основе типа класса.

0 голосов
/ 29 июня 2009

Если у вас есть ссылка на форму, и это может быть прямоугольник или пентаграмма или что-то еще, и вы хотите «преобразовать» в круг (я полагаю, вы имеете в виду круг с таким же ограничивающим прямоугольником?), У вас создать новый объект. Вы не можете изменить класс объекта после того, как он был создан (за исключением очень неприятных низкоуровневых хаков).

Так что да, вы бы создали -initWithShape: метод в классе Circle. Но метод будет выглядеть как обычный метод init, устанавливающий переменные экземпляра нового объекта Circle ('self'). Он получит доступ к свойствам данного Shape, таким как его положение и размер, и соответственно настроит новый объект.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...