2015-09-09 41 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