子类化问题:子类的字典值?

时间:2019-04-16 01:49:58

标签: swift

短篇小说:

我试图创建一个其子类可以具有更专门的成员的类(字典),然后出现以下错误:

error: property 'dict' with type '[Int : B]' cannot override a property with type '[Int : A]'

这是我的代码:

class A {}
class B: A {}               // subclass of A

let dict = [Int:B]()
print(dict is [Int:A])      // true

class MyDict {
  var dict = [Int:A]()
}

class MyDict2: MyDict {

  /*
    ⛔ error: 
        property 'dict' with type '[Int : B]' cannot override a property with type '[Int : A]'
  */
  override var dict = [Int:B]()

}

我的问题是,由于[Int:B]的实例是[Int:A],为什么我们不能用[Int:A]覆盖[Int:B]类型的字典?

长篇故事:

实际上,我试图为加权图和未加权图设计类型。以下是我的实现:

// unweighted edge
public class Edge<Vertex:Hashable> {
  public let start: Vertex
  public let end  : Vertex
  init(from start: Vertex, to end: Vertex) {
    self.start = start
    self.end   = end
  }
}

// weighted edge
public class WeightedEdge<Vertex:Hashable, Weight:Comparable> : Edge<Vertex> {
  public let weight: Weight
  init(from start:Vertex, to end:Vertex, weight:Weight) {
    self.weight = weight
    super.init(from:start, to:end)
  }
}

// unweighted graph (definition)
public class Graph<Vertex:Hashable> {

  // edges dictionary
  var edgesOf = [Vertex: [Edge<Vertex>]]()

  // g.addEdge(from:to:bidirectional:)
  public func addEdge(
    from start: Vertex, 
    to end:Vertex, 
    bidirectional:Bool = false
  ) {
    edgesOf[start, default:[]].append(Edge(from: start, to:end))
    if bidirectional {
      edgesOf[end, default:[]].append(Edge(from: end, to:start))
    }
  }

}

// weighted graph (definition)
public class WeightedGraph<Vertex:Hashable, Weight:Comparable> : Graph<Vertex> {

  public override func addEdge(from start:Vertex, to end:Vertex, bidirectional:Bool = false) {
    fatalError("Can't add an unweighted edge to a weighted graph❗")
  }

  // g.addEdge(from:to:weight:bidirectional:)
  public func addEdge(
    from    start: Vertex, 
    to        end: Vertex, 
    weight       : Weight,
    bidirectional: Bool = false
  ) {
    edgesOf[start, default:[]].append(
      WeightedEdge(from: start, to:end, weight:weight)
    )
    if bidirectional {
      edgesOf[end, default:[]].append(
        WeightedEdge(from: end, to:start, weight:weight)
      )
    }
  }

}

let g = WeightedGraph<Int,Int>()
g.addEdge(from: 3, to: 4, weight:7, bidirectional: true)
g.addEdge(from: 1, to: 3)  // fatalError

它对我来说很好,但是我为它的丑陋部分感到困扰:

public override func addEdge(from start:Vertex, to end:Vertex, bidirectional:Bool = false) {
  fatalError("Can't add an unweighted edge to a weighted graph❗")
}

如何防止加权图向自身添加未加权的边?

1 个答案:

答案 0 :(得分:0)

当您继承一个类时,您将在其中包含超类,因此您将获得同一属性的冲突定义,MyDict2的编译版本将有所简化

class MyDict2 {
    var dict = [Int:A]()
    var dict = [Int:B]() 
}

,如您所见,这将不起作用。或者,将替换dict属性,但是您遇到的问题是,任何接受类型为MyDict的参数的函数也可以采用MyDict2的实例,但是如果该函数访问了{{ 1}}属性,它将发现类型为dict的值,而该函数将不知道什么是什么,因为它被定义为采用B,因此只知道MyDict

我不认为继承是解决问题的替代方法,替代方法是拥有两个单独的类,这些类符合访问底层存储(dict)的相同协议或使用泛型实现

A