2015-09-09 70 views
4

這與this question相關。使用typealias,我可以創建一個具有「children」var但具有特定類型的類,這正是我正在尋找的。但是當我這樣做時,我不能再測試以查看實例是否遵循該協議。我也試過'如果讓',那不行。有沒有辦法做到這一點?測試實例是否是Swift中的typealias協議?

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

protocol Child { 
    typealias Parent 
    var parent: Parent { get set } 

} 

class Foo: Parent { 
    var children = [Bar]() 

    init(){} 
} 

class Bar: Child { 
    var parent = Foo() 
} 

let testVar = Foo() 
let cVar = Bar() 

testVar.children.append(cVar) 
cVar.parent = testVar 

//I get the error here saying protocol is limited to generic constraints 
if testVar is Parent { 

} 
+1

其實我不認爲這會多大意義(該編譯器有其原因)或用於某些事情。你可以用你的意圖擴展你的問題嗎? – Kametrixom

+0

@Kametrixom我有大約5個不同的類具有相同的變量「孩子」,有些具有相同的變量「父母」。這些都有一些共同點,但有時候不是類型檢查我喜歡鍵入的每一個類型檢查是否它是一個父類,這意味着它保證有一個「子」變量,我想訪問。 – MAH

回答

4

不幸的是,沒有辦法解決這個問題(至少現在是這樣)。所以更具動態性的方法是建立一個沒有自身相關類型要求的「超級」協議。這允許您將這些「超級」的協議之間進行轉換:

protocol _Parent { 
    var anyChildren: [Any] { get set } 
} 
protocol Parent: _Parent { 
    typealias Child 
    var children: [Child] { get set } 
} 

extension Parent { 
    // requirement of _Parent 
    var anyChildren: [Any] { 
     get { 
      return children.map{ $0 as Any } 
     } 
     set { 
      // use `as!` and `map` if you are sure that all elements are of type Child 
      // or if you want a crash if not 
      children = newValue.flatMap{ $0 as? Child } 
     } 
    } 
} 

protocol _Child { 
    var anyParent: Any { get set } 
} 

protocol Child: _Child { 
    typealias Parent 
    var parent: Parent { get set } 
} 

extension Child { 
    // requirement of _Child 
    var anyParent: Any { 
     get { 
      return parent 
     } 
     set { 
      parent = newValue as! Parent 
     } 
    } 
} 

現在你可以使用它們的屬性來操作數據:

class Foo: Parent { 
    var children = [Foo]() 
} 

let anything: Any = Foo() 

// use `if let` and `as?` instead of `is` in order to have a more static type 
if let aDynamicParent = anything as? _Parent { 
    aDynamicParent.anyChildren.map{ $0 as! Foo } // cast the array back to its original type 

    aDynamicParent.children = [Foo(), Foo(), Foo()] 
} 
+0

從來沒有想過這樣做,但這將工作。我想現在是一種解決方法,但仍然希望下一個版本的Swift能夠實現這樣的功能。 – MAH

0

你不需要ChildParent類型別名如果Parent包含符合Child協議和Child包含Parent協議屬性的對象數組。

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

protocol Child { 
    var parent: Parent { get nonmutating set } 
} 

class Foo: Parent { 
    var children: [Child] 
    init(children: [Child]) { 
     self.children = children 
     self.children.forEach { $0.parent = self } 
    } 
} 

class Bar: Child { 
    var parent: Parent 
    init(parent: Parent) { 
     self.parent = parent 
     self.parent.children.append(self) 
    } 
} 

let testVar = Foo(children: [Bar]()) 
let cVar = Bar(parent: testVar) 

let parent = testVar as Parent 
let children = parent.children 
+0

但是如果我想Foo的孩子只能是Bar類型呢? – MAH