Element是否可以返回引用其通用Container? (迅速)

时间:2016-09-17 04:33:14

标签: swift oop generics

实施例II

最初的例子是不合适的,正如有些人指出的那样(我现在同意,谢谢)。所以我提出了一个新的,一个更复杂的。顺便说一下,如果你能帮助我在更抽象的层面上理解这一点,我将非常感激。

class Employee {
    var department :Department? = nil

    func leader() -> Employee {
       return self.department!.director
    }
}

class Designer :Employee {
    func design() {
        // Draw some blueprint
    }
}

class Developer :Employee {
    func develop() {
        // Write some code
    }
}

class Department <E: Employee> {
    let employees :[E]
    let director :E

    init(employees :[E], director :E) {
        self.employees = employees
        self.director = director
        for e in self.employees {
            e.department = self
        }
    }
}

Error

示例I

我正在实施类似纸牌游戏的东西。

class Suit <C :Card> {
    public let cards :[C]

    init(cards :[C]) {
        self.cards = cards
    }

    convenience
    init() {
        self.init(cards: Array(1...13).map({ C(faceValue:$0) }))
        for card in self.cards {
            card.suit = self
        }
    }
}

class Card {
    public let faceValue :UInt
    public internal(set) var suit :Suit? = nil

    required
    init(faceValue :UInt) {
        self.faceValue = faceValue
    }
}

我希望每张卡都有一个参考回到它所属的套装。 我面临的问题是套装是一个通用类。 所以,我有这个错误:

The error I am suffering from

有什么想法来解决这个问题?感谢

1 个答案:

答案 0 :(得分:1)

你所拥有的是部分多态的,部分是通用的。要使其工作,请将通用部分(部门及其可包含的内容)与多态部分(Employee类层次结构)分开。

快速修复

// A protocol to define what the department can hold:

protocol Employable {
    weak var department :Department<Self>? { get set }
}

// A generic department to hold objects that conform to the Employable protocol:

class Department <E: Employable> {
    let employees :[E]
    let director :E

    init(employees :[E], director :E) {
        self.employees = employees
        self.director = director
        for var e in self.employees {
            // e is defined as var rather than defaulting to let
            e.department = self
        }
    }
}

// The polymorphic Employee hierarchy:

class Employee : Employable {
    weak internal var department: Department<Employee>?

    func leader() -> Employee {
        return self.department!.director
    }
}

class Designer :Employee {}

class Developer :Employee {}

这可以让您的示例发挥作用,但现在您可以更进一步。

使用通用集合

将Employable和Department重命名为generic:

protocol MyCollectable {
    weak var collection :MyCollection<Self>? { get set }
}

class MyCollection <E: MyCollectable> {
    let members :[E]
    let leader :E

    init(members :[E], leader :E) {
        self.members = members
        self.leader = leader
        for var e in self.members{
            e.collection = self
        }
    }
}

现在你可以这样做:

class Employee : MyCollectable {
    weak internal var collection: MyCollection<Employee>?

    func leader() -> Employee {
        return self.collection!.leader
    }
}

class Designer :Employee {}
class Developer :Employee {}

var department = MyCollection<Employee>(members: [Designer()], leader: Designer())

和此:

class Canine : MyCollectable {
    weak internal var collection: MyCollection<Canine>?
}

class Wolf : Canine {}
class Dog : Canine {}

var pack = MyCollection<Canine>(members: [Wolf(),Dog()],leader: Wolf())
var wolfPack = MyCollection<Wolf>(members: [Wolf(),Wolf()], leader: Wolf())

但是你受到了保护:

var wolfPack = MyCollection<Wolf>(members: [Wolf(),Dog()], leader: Wolf())

或者这个:

var wolfPack = MyCollection<Wolf>(members: [Wolf(),Designer()], leader: Wolf())

<强>更新

替代使用收集协议和可收集

protocol MyCollectable {
    associatedtype MyCollection
    var collection :MyCollection? { get set }
}

protocol MyCollection {
    associatedtype MyCollectable
    var members:[MyCollectable] { get }
    var leader:MyCollectable { get }
}

class Employee : MyCollectable {
    typealias MyCollection = Department
    internal var collection: Department?
}

class Department : MyCollection {
    typealias MyCollectable = Employee
    let members :[MyCollectable]
    let leader :MyCollectable

    init(members :[MyCollectable], leader :MyCollectable) {
        self.members = members
        self.leader = leader
        for e in self.members{
            e.collection = self
        }
    }
}

class Designer:Employee {}
class Developer:Employee {}
var dept = Department(members: [Designer(), Designer()],leader: Developer())

最后,请注意,除非管理对象,否则反向引用是一个坏主意,例如通过核心数据存储,其中后向引用是反向关系。