2015-08-01 16 views

cevap

6

children dizi AnyObject girişlerini kabul etmek gerekir anlamına gelir. Ama Bar 'in çocuklarının sadece Foo nesnesi olmasını istediğiniz gibi görünüyor.

Bunun yerine, protokolünü verebilir bir associated type:

protocol Parent { 
    associatedtype Child 
    var children: [Child] { get set } 
} 

class Foo { } 

class Bar: Parent { 
    var children = [Foo]() 
    init() {} 
} 
+0

. Ben Swift'i kontrol eden bir tip hayranım ama bazen bir ton kod oluşturmaya zorluyor. Yazılımımda birçok sınıfım var ve hepsinin aynı özelliği sahiplenmenin sinir bozucu olabileceğini garanti ettikleri zaman tek tek kontrol etmem gerekiyor. – MAH

+1

@MAH Nesneler için ortak işlevler sağlamak için protokolleri de kullanabilirsiniz. “Çocuk” bir protokol olsaydı, o zaman “var çocuklar: [Çocuk]”, “Çocuk” ile uyumlu herhangi bir öğe dizisinden tatmin olabilirdi. İşlevselliği genelleştirmekte özgürsünüz ve ayrı ayrı davaları kontrol etmek zorunda kalmayın! – jtbandes

+0

[Protokol yönelimli programlama] (https://developer.apple.com/videos/wwdc/2015/?id=408) konuşması bir saattir. – jtbandes

1

protokol alıcı ve tipi [AnyObject] arasında ayarlayıcı böyle bir alıcı ve ayarlayıcı, bu sınıfın değil alt tipi olmak zorunda olduğu anlamına gelir daha orada olduğunu beyan ederse.

Kodunuz ediyorum mantıksal olarak yanlış - örneğin [Foo] değişkenine [sınıf] [Int] (protokolün mümkün olduğunu söyler) belirleyebildiğiniz için (örneğin bu varyasyon var)

Yani bu aslında tek doğru yol.

protocol Parent { 
    var children: [AnyObject] { get set } 
} 

class Foo { 
} 

class Bar: Parent { //error happens here 
    var children = [AnyObject]() 

    init() {} 
} 

Hızlı 2.0 typealias başka bir seçenek olabilir.

0

Hayır, bir özelliğin türünü değiştiremezsiniz.

sizin çubuk sınıfına ekleyin: protokolde AnyObject Gerektiren

var childrenObject: Foo { 
    get { 
     return self.children as! Foo 
    } 
} 
2

her zaman Sınıfındaki bunu belirtmek zorunda AnyObject türü bir dizi isterseniz:

class Bar: Parent { 
    var children = [AnyObject]() 
    init() {} 
} 

ama eğer bir typealias ile daha spesifik bir protokolü kullanan bu kadar sever protokolü yazabilirsiniz:

protocol Parent { 
    // in Swift 1 and 2: use `typealias` instead of `associatedtype` 
    associatedtype T: AnyObject // this makes sure that all instances in the array are definitely of type `AnyObject`/classes 
    var children: [T] { get set } 
} 

Bu şekilde sınıf eserlerin senin eski uygunluk ancak bu protokol sadece genel kısıtlaması olarak kullanılabilir ve bu nedenle sadece fonksiyonlarının ve jenerik beyanlarında ki düşünmek zorundayız:

// --- this does work 
func someFunc<T: Parent, U: Parent>(p1: T, p2: U) { /* ... */ } 

class SomeClass<T: Parent> { /* ... */ } 


// --- this doesn't work 
let parent: Parent 
let array: [Parent] 
// here you can only use types which conform to the protocol 
// but not the protocol itself as generic arguments 
let something = SomeClass<Parent>() 
0

verebilir protokol cevap Alternatif Bazı protokoller size yarar değil. İlgili

class Parent<T : RawRepresentable> where T.RawValue == Int { 
    var value : T 

    init(withValue v : T) { 
     self.value = v 
    } 
} 

enum testOne : Int { 
    case one 
    case two 
} 

enum testTwo : Int { 
    case three 
    case four 
} 

class ChildOne : Parent<testOne> {} 

class ChildTwo : Parent<testTwo> {} 

let c1 = ChildOne(withValue: testOne.one) 
print(c1.value) 
let c2 = ChildTwo(withValue: testTwo.three) 
print(c2.value) 

: Tam olarak ne gerekli How in Swift specify type constraint to be enum?

İlgili konular