I would suggest the following:
class Parent {
// func m(x0: Int, x1: Int = 0, x2: Int = 0) -> String {
// return "\(x0), \(x1), \(x2)"
// }
func m(x0: Int) -> String {
return m(x0: x0, x1: 0, x2: 0)
}
func m(x0: Int, x1: Int) -> String {
return m(x0: x0, x1: x1, x2: 0)
}
func m(x0: Int, x2: Int) -> String {
return m(x0: x0, x1: 0, x2: x2)
}
func m(x0: Int, x1: Int, x2: Int) -> String {
return "\(x0), \(x1), \(x2)"
}
}
class Child: Parent {
// override func m(x0: Int, x1: Int = -1, x2: Int = -1) -> String {
// return super.m(x0: x0, x1: x1, x2: x2)
// }
override func m(x0: Int) -> String {
return m(x0: x0, x1: -1, x2: -1)
}
override func m(x0: Int, x1: Int) -> String {
return m(x0: x0, x1: x1, x2: -1)
}
override func m(x0: Int, x2: Int) -> String {
return m(x0: x0, x1: -1, x2: x2)
}
override func m(x0: Int, x1: Int, x2: Int) -> String {
return super.m(x0: x0, x1: x1, x2: x2)
}
}
class Grandchild: Child {
// override func m(x0: Int, x1: Int = -2) -> String { // Note only x1 redefined
// return super.m(x0: x0, x1: x1)
// }
override func m(x0: Int) -> String {
return m(x0: x0, x1: -2)
}
override func m(x0: Int, x1: Int) -> String {
return super.m(x0: x0, x1: x1)
}
}
func test(_ p: Parent, _ x: Int) {
print(p.m(x0: x)) // x, d, d
print(p.m(x0: x, x1: 1)) // x, 1, d
print(p.m(x0: x, x2: 2)) // x, d, 2
print(p.m(x0: x, x1: 1, x2: 2)) // x, 1, 2
}
test(Parent(), 0)
//0, 0, 0
//0, 1, 0
//0, 0, 2
//0, 1, 2
test(Child(), -1)
//-1, -1, -1
//-1, 1, -1
//-1, -1, 2
//-1, 1, 2
test(Grandchild(), -2)
//-2, -2, -1
//-2, 1, -1
//-2, -1, 2
//-2, 1, 2