/ / Общи ограничения и инициализиращо наследство в Swift - swift, generics, swift3, swift-protocols

Генерични ограничения и Инициализация на наследство в Swift - бързи, генерични, бързи3, бързи протоколи

Опитвам се да се обадя на инициализатор, изискван от протокола A на тип, който съответства на двата вида A и е подклас на C.

Всичко е добре и добре, ако C е базов клас. Но веднага след това C подкласове друг клас, да речем B, тя се разпада.

Ето какво говоря за:

protocol A {
init(foo: String)
}

class B {
init() {}
}

class C: B {}

func makeSomething<T: A>() -> T where T: B {
return T(foo: "Hi")
}

Това работи. Но ако се променя where T: B да се where T: C, Получавам следната грешка: argument passed to call that takes no arguments, Ще ми позволи само да се обадя Bс init.

Защо не мога да нарека този инициализатор? Разбирам, че суперкласът има свои определени инициализатори, които трябва да се извикат. Но това ще се наложи, когато някой всъщност напише клас, който подкласове B и отговаря на A, (Напр. Реализиране init(Foo: String) и обаждане super.init(bar: Int) вътре).

Всяка помощ тук ще бъде много оценявам. Благодаря!

Отговори:

0 за отговор № 1

Swift осигурява инициализатор по подразбиране за основния ви клас, ако има всички инициализирани свойства, но не и обекти на Generics, защото Swift може да мисли, че неговите свойства не са инициализирани.

Така че, когато ограничите вашия тип връщане като

func makeSomething<T: A>() -> T where T: C

Тя изисква инициализация за клас C, тъй като Swift не може да осигури инициализатор по подразбиране

func makeSomething<T: A>() -> T {
return T(foo:"string")
}

Ако искате да се върнете return T(foo: "Hi") :

Вие получавате грешка, защото клас C няма инициализатор, който приема init(foo: String)

Променете клас C като

class C: A {
required init(foo: String) {

}
}

който осигурява поне един инициализатор, който приема типа аргумент.

Така че, не забравяйте, ако не подклас "Има вече един инициализатор върши работата си и не получават грешка.