2014-06-20 3 views
6

Я пытался реализовать новый метод для объединения двух Array, возвращая Array, содержащий общий тип данных для двух других.Принудительный суперкласс в Swift Generics

Чтобы сохранить его ясно, я ожидал бы способ сделать что-то вроде (зная, что синтаксис не правильно ...):

@infix func + <T,U,X where X super T, X super U>(left : Array<T>, right : Array<U>) 
-> Array<X>{ 
    //join both arrays 
} 

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

+0

Замените 'super' на': '. Как и в «T: X», в котором говорится, что T должен быть X, где X является либо протоколом, либо классом. –

+2

Это работает? Если да, напишите какой-нибудь реальный код. Я не могу заставить синтаксис работать. @infix func + (слева: T [], справа: U []) -> X [] {... имеет ошибку 'Тип U ограниченный для не-протокола типа X ' – Grimxn

+0

@Grimxn извините за задержку ответа. Я получаю сообщение об ошибке (Тип T ограничен не-протоколом типа X). Но я должен признать, что ваше решение выглядит хорошо. Почему это невозможно? – khose

ответ

0

Вы можете использовать синтаксис : следующим образом: определение типа

// The parameter must be a UIViewController, or subclass 
func changeViewColor<T: UIViewController>(vc: T) { 
    vc.view.backgroundColor = UIColor.redColor() 
} 
1

Свифта умнее, чем вы думаете. Секрет заключается в том, чтобы посмотреть на подписи оператора ноля-коалесцирующего ??:

func ??<T>(optional: T?, defaultValue: @autoclosure() -> T) -> T 
func ??<T>(optional: T?, defaultValue: @autoclosure() -> T?) -> T? 

Это ясно при использовании этого оператора, что это будет способствовать T быть ближайшим общим предком любого типа, переданного ему, все пути до Any, например:

let i: Int? = 3 
let s: String? = "3" 
let a: Any? = i ?? s 

компилируется и работает, но тип a является Any (который на самом деле является протокол). В некоторых случаях вам нужно предоставить доказательства типа для компилятора, а в некоторых случаях вы этого не сделаете. Если типы имеют общий предок, который не является протоколом, представляется, что доказательства не нужны. Вы можете думать, что ?? получает специальную обработку от компилятора, но это не так. Вы можете очень легко сворачивать.

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

Если бы мы должны были реализовать + как функцию, она будет выглядеть следующим образом:

func joinArrays<T>(array1: [T], array2: [T]) -> [T] { 
    return array1 + array2 
} 

class Base {} 
class Derived1 : Base {} 
class Derived2 : Base {} 

let a1 = [Derived1(), Derived1()] 
let a2 = [Derived2(), Derived2()] 
let a = joinArrays(a1, a2) 

Тип a является Array<Base>, потому что это ближайший общий предок параметров универсального типа.

Я использовал этот «тип продвижения», чтобы создать всевозможные сложные коалесцирующие/монадические операторы, à la Haskell. Единственное недоразумение заключалось в том, что Swift не поддерживает ковариацию параметров родового типа.

Смежные вопросы