参考自身的泛型类

时间:2017-03-23 21:13:35

标签: swift generics

我在Swift中有以下类:

class A {}; class B {}

class Collection<T> {
    var parent: Collection?
}

当我想构建像

这样的层次结构时
var rootCol = Collection<A>()
var childCol = Collection<B>()
childCol.parent = rootCol

最后一行产生此错误:

Cannot assign value of type 'Collection<A>' to type 'Collection<B>?'

parent必须使用哪种类型,以便可以为其分配不同的泛型类型?

2 个答案:

答案 0 :(得分:0)

问题是您尝试将Collection<A>类型的实例分配给Collection<B>?类型的变量,这是不可能的,您只能将Collection<A>分配给Collection<A> }或Collection<B>Collection<B>。 虽然您没有在父类型的末尾写<T>,但是快速推断出类型为Collection<T>,然后也是可选的。 在这种情况下,我建议使用协议。

还有一件事,建议不要使用与swift协议冲突的类的名称。

class A {}
class B {}

protocol Foo{}

class Bar<T>:Foo {
    var parent: Foo?
}

var rootCol = Bar<A>()
var childCol = Bar<B>()
childCol.parent = rootCol

答案 1 :(得分:0)

您的结构可以是使用基于所包含数据的泛型类(可以同时适用于引用和值类型)的“容器”树。

例如:

class TreeOf<T>
{
   var value:T?               = nil
   weak var parent:TreeOf<T>? = nil
   var children:[TreeOf<T>]   = []

   init(_ value:T? = nil)
   { self.value = value }

   func addChild(_ value:T) -> TreeOf<T>
   { 
      let newNode = TreeOf<T>()
      newNode.value = value
      children.append(newNode)
      return newNode 
   } 
}

var directory = TreeOf<String>("/")

directory.addChild("usr")
directory.addChild("library")
let users = directory.addChild("users")
users.addChild("paul")
users.addChild("John")
users.addChild("Mary")

let userNames = directory.children[2].children.map{$0.value}

或者您的树节点本身(即在树结构中链接的对象)可以实现链接变量并使用通用协议来免费获取所有树操作功能。但是,这只适用于引用类型,需要最终的类。

例如:

protocol TreeNode:class 
{
   var parent    :Self?         { get set }
   var children  :[Self]        { get set }
}   

extension TreeNode 
{   
   func removeFromParent()
   { 
     parent?.children = parent!.children.filter{$0 !== self}
     parent = nil 
   }

   func childOf(_ newParent:Self) -> Self  
   { 
     removeFromParent()
     parent = newParent
     newParent.children.append(self)
     return self 
   }

   // ... more generic tree related functions provided by protocol for all classes
   // e.g. root, count descendants, searches, traversal, prune and graft, etc.
}

final class FamilyMember:TreeNode
{
   var parent:FamilyMember?    = nil
   var children:[FamilyMember] = [] 

   var name = ""
   init(_ newName:String) {name = newName} 
}

let paul  = FamilyMember("Paul")
let mary  = FamilyMember("Mary").childOf(paul)
let john  = FamilyMember("John").childOf(paul)
let suzie = FamilyMember("Suzie").childOf(mary)
let luke  = FamilyMember("Luke").childOf(mary)
let irene = FamilyMember("Irene").childOf(john)

let miniPaul = paul.children.map{$0.name}
let miniMary = mary.children.map{$0.name}