Short Story:
I was trying to make a class whose subclass can have a more specialized member (a dictionary), then I hit the following error:
error: property 'dict' with type '[Int : B]' cannot override a property with type '[Int : A]'
Here is my code:
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]()
}
My question is that since an instance of [Int:B]
is a [Int:A]
, why can't we override a dictionary of type [Int:A]
with [Int:B]
?
Long Story:
Actually, I was trying to design types for both weighted and unweighted graphs. The following is my implementation:
// 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
It works fine for me, but I'm bothered by the ugly part of it:
public override func addEdge(from start:Vertex, to end:Vertex, bidirectional:Bool = false) {
fatalError("Can't add an unweighted edge to a weighted graph❗")
}
What can I do to prevent a weighted graph from adding an unweighted edge to itself?