Хорошая практика для унизительного типа возврата унаследованных функций - PullRequest
3 голосов
/ 27 июня 2011

У меня есть Matrix -класс, из которого Vector -класс получен из-за дополнительной функциональности и лучшего использования У меня есть Vector3 -класс, который получен из Vector класса.Моя проблема в том, что класс Vector реализует функцию, например, +normalizeVector:, которая возвращает новый выделенный экземпляр Vector.Подкласс Vector3 должен наследовать эти две функции, но наследование приводит к прототипам функций, которые возвращают экземпляр Vector, а не экземпляр Vector3.Это как наследование работает, но есть ли хорошая практика, как решить эту проблему?Наивным решением является создание Vector3 также нового класса, подклассы которого NSObject, но я хочу, чтобы Vector - и Vector3 - экземпляры могли легко взаимодействовать.

Вот пример кода:

@interface Vector : NSObject {
....
}
+(Vector*) normalizeVector:(Vector*)v; //returns a new allocated Vector-instance
-(Vector*) normalize; //normalizes itself and returns itself
-(Vector*) otherFunction;
@end

@interface Vector3 : Vector {
}
-(Vector3*) specialFunction;
@end

использование этого кода:

Vector3 *v3 = ...;
[[v3 normalize] specialFunction]; //Compiler gives me a warning because Vector has no specialFunction. Cast would help
[[Vector3 normalizeVector:v3] specialFunction]; //Compiler gives me a warning and during runtime it will crash because a `Vector` doesn't implement specialFunction

приведение к Vector3 поможет, но работать с ним неудобнои это также терпит неудачу со статической функцией +normalizeVector:, потому что в этой статической функции выделяется Vector -экземпляр и приведение указателя не помогает.

Есть идеи?или другие подходы / другое моделирование?

edit: Код для моей статической функции normalizeVector, которая наследуется Vector3:

@implementation Vector
...
+(Vector*) normalizeVector:(Vector *)v
{
    unsigned int dim = vector_max(v.cols, v.rows);
    Vector *res = [[[Vector alloc]initAsColumnVectorWithDim:dim] autorelease];
    [Vector normalizeVector:v destination:res]; // this does only the logic: calc length and divide each component by the len and store at the vector passed to destination
    return res;
}
@end

Ответы [ 2 ]

4 голосов
/ 27 июня 2011

Вы заметите, что методы -init всегда возвращают идентификатор типа -(id)init {..} именно из-за этого.

Кроме того, вместо [Vector alloc] - как вы заметили, вы фактически не знаете, в каком классе вы находитесь во время выполнения (это может быть подкласс), поэтому вместо этого просто используйте [self alloc] где self - текущий класс, потому что вы находитесь в методе Class. Итак, если вы сделаете [Vector3 normalizeVector:v], то self будет Vector3 , а если вы сделаете [Vector normalizeVector:v], то self будет Vector .

Попробуйте настроить свой + normailzeVector: метод на

+ (id)normalizeVector:(Vector *)v {
    unsigned int dim = vector_max(v.cols, v.rows);
    id res = [[[self alloc] initAsColumnVectorWithDim:dim] autorelease];
    [self normalizeVector:v destination:res];
    return res;
}

Просто примечание, + (id)normalizeVector: не является функцией и определенно не является статической функцией. Это метод класса, он просто помогает правильно понять условия.

1 голос
/ 27 июня 2011

В этом случае я бы сделал normaliseVector методом экземпляра.Поэтому вместо

Vector * newV = [Vector normalizeVector: v];

call

Vector * newV = [v normalizeVector];

Тогда выможет создать другой вектор нормализации для вектора и вектора3

РЕДАКТИРОВАТЬ: для [[v3 normalize] specialFunction];Существует проблема в том, что normalize может иногда возвращать объект, на котором specialFunction не работает, то есть он работает, только если v3 является Vector3.Так что в этом случае у вас есть дополнительная информация, так что каст будет необходим, или что Vector3 normailze отличается от Vector.В этом случае я бы создал метод покрытия в Vector3 для вызова normalize] specialFunction], чтобы приведение происходило в специальном коде Vector3.

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