Вам просто нужно общее дополнение:
func +<A: Angle>(lhs: A, rhs: Angle) -> A {
return A(rawRadians: lhs.rawRadians + rhs.rawRadians)
}
Таким образом, добавление вернет любой тип, указанный слева.
Вообще говоря, если вы используете dynamicType
, вы, вероятно, боретесь со Swift. Swift больше полагается на дженерики и протоколы (т. е. информацию о статическом типе во время компиляции), а не на динамическую диспетчеризацию (т. е. информацию о динамическом типе во время выполнения).
В этом коде, как вы говорите, A
является заполнителем для «некоторого типа, соответствующего Angle
, который должен быть определен во время компиляции». Итак, в вашем первом примере:
Degrees(180) + Rotations(0.25) --> Degrees(270)
На самом деле это вызывает специализированную функцию +<Degrees>
. И это:
Rotations(0.25) + Radians(M_PI) -> Rotations(0.75)
вызывает (логически) другую функцию с именем +<Rotations>
. Компилятор может оптимизировать эти функции в одну функцию, но логически они являются независимыми функциями, созданными во время компиляции. По сути, это ярлык для написания addDegrees(Degrees, Angle)
и addRotations(Rotations, Angle)
вручную.
Теперь, что касается вашего вопроса о функции, которая принимает два угла и возвращает... ну, что? Если вы хотите вернуть Angle
в этом случае, это легко и точно соответствует вашей исходной подписи:
func +(lhs: Angle, rhs: Angle) -> Angle {
return Radians(rawRadians: lhs.rawRadians + rhs.rawRadians)
}
«Но…» вы говорите, «это возвращает Radians
». Нет, это не так. Он возвращает Angle
. Вы можете делать с ним все, что захотите. Детали реализации непрозрачны, как и должно быть. Если вас волнует, что базовая структура данных является Radians
, вы почти наверняка делаете что-то не так.
Хорошо, есть один случай, когда это может быть полезно знать, и это если вы распечатываете вещи, основываясь на том, как вы их делаете. Итак, если пользователь дал вам информацию о степени для начала, вы хотите напечатать все в градусах (используя метод description
, который вы не упомянули). И, возможно, это стоит сделать в этом конкретном случае. Если хотите, ваш исходный код был очень похож:
func +(lhs: Angle, rhs: Angle) -> Angle {
return lhs.dynamicType.init(rawRadians: lhs.rawRadians + rhs.rawRadians)
}
Но важно понимать, что это не соответствует вашему запросу на наличие «аргумента lhs для указания типа возвращаемого значения». Это приводит к тому, что аргумент lhs определяет реализацию возврата. Возвращаемый тип всегда Angle
. Если вы хотите изменить возвращаемый тип, вам нужно использовать дженерики.
person
Rob Napier
schedule
25.09.2015