Swift 2.0:参数化类不';t调用proper==函数,如果它从可等式的类继承

Swift 2.0:参数化类不';t调用proper==函数,如果它从可等式的类继承,swift,class,operator-overloading,overloading,language-lawyer,Swift,Class,Operator Overloading,Overloading,Language Lawyer,当一个参数化类从另一个符合equalable的类继承时,=调用超类的=。有人能解释为什么会发生这种情况和/或我是如何在这里做错事情的吗?我相信一个例子最能说明我的问题: public class Foo: Equatable {} public func ==(lhs: Foo, rhs: Foo) -> Bool { return false } //Parametrized public class Bar<T: Equatable>: Foo { public va

当一个参数化类从另一个符合
equalable
的类继承时,
=
调用超类的
=
。有人能解释为什么会发生这种情况和/或我是如何在这里做错事情的吗?我相信一个例子最能说明我的问题:

public class Foo: Equatable {}
public func ==(lhs: Foo, rhs: Foo) -> Bool { return false }

//Parametrized
public class Bar<T: Equatable>: Foo {
  public var bar: T?
  public init(barIn: T?) {
    self.bar = barIn
  }
}
public func ==<T>(lhs: Bar<T>, rhs: Bar<T>) -> Bool { return lhs.bar == rhs.bar }

//Non parametrized
public class Baz: Foo {
  public var baz: Int?
  public init(bazIn: Int?) {
    self.baz = bazIn
  }
}
public func ==(lhs: Baz, rhs: Baz) -> Bool { return lhs.baz == rhs.baz }

//Parametrized, no inheritance
public class Qux<T: Equatable>: Equatable {
  public var qux: T?
  public init(quxIn: T?) {
    self.qux = quxIn
  }
}
public func ==<T>(lhs: Qux<T>, rhs: Qux<T>) -> Bool { return lhs.qux == rhs.qux }

Bar<Int>(barIn: 1) == Bar<Int>(barIn: 1) //false
Baz(bazIn: 1) == Baz(bazIn: 1) //true
Qux(quxIn: 1) == Qux(quxIn: 1) //true, of course
公共类Foo:equalable{}
public func==(lhs:Foo,rhs:Foo)->Bool{return false}
//参数化
公共类酒吧:富{
公共变量栏:T?
公共初始化(barIn:T?){
self.bar=barIn
}
}
public func==(lhs:Bar,rhs:Bar)->Bool{return lhs.Bar==rhs.Bar}
//非参数化
公共类Baz:Foo{
公共变量baz:Int?
公共初始化(bazIn:Int?){
self.baz=bazIn
}
}
public func==(lhs:Baz,rhs:Baz)->Bool{return lhs.Baz==rhs.Baz}
//参数化,无继承
公共类Qux:可平等{
公共变量qux:T?
公共初始化(曲欣:T?){
self.qux=quxIn
}
}
public func==(lhs:Qux,rhs:Qux)->Bool{return lhs.Qux==rhs.Qux}
Bar(barIn:1)=Bar(barIn:1)//错误
Baz(bazIn:1)=Baz(bazIn:1)//真
Qux(quxIn:1)==Qux(quxIn:1)//当然是真的

不能说我是Swift运算符重载的专家,但我发现您可以找到一些有用的信息:

对于引用类型,等式将与标识合并。信息技术 两个具有相同值的名称结构应该相等, 但两个人对象可以有相同的名称,但可以不同 人们

对于与Objective-C兼容的对象类型,==运算符已经存在 由isEqual提供:方法: .... 对于Swift引用类型,相等性可以作为标识进行计算 检查用该实例构造的
ObjectIdentifier
类型:

请考虑这个:

为以下数组调用的相等性的原因: 包含B以解决自由函数的重载问题 静态地,而不是动态地——也就是说,在编译时基于 类型,而不是在运行时基于指向的值

这并不奇怪,因为类中没有声明==并且 然后在子类中重写。这似乎非常有限,但是 老实说,使用传统的OO定义多态平等 技术是极其困难的。看到和 更多信息

天真的解决方案可能是定义一个动态调度的 函数,然后定义
=
来调用它:。。。那么当你 实施B时,您将覆盖
equalTo

因此,可能是您的代码无法工作的原因是编译器在静态解析后调用它,这是在不知道您将覆盖
=
某些
Foo
操作符的情况下完成的
可能您应该这样做(相等逻辑移动到从运算符调用的函数:

public class Foo: Equatable {
  func equalTo(rhs: Foo) -> Bool {
    // base logic here
  }
}
public func ==(lhs: Foo, rhs: Foo) -> Bool {
  // check for type here and call appropriate function]
  // may be this will be done automatically as Bar overloads equalTo function
  return lhs.equalTo(rhs)
}

public class Bar<T: Equatable>: Foo {
  public var bar: T?
  public init(barIn: T?) {
    self.bar = barIn
  }
  override func equalTo(rhs: Foo) {
    // cast rhs to Foo here
    // if it can't be done, return false
    return (rhs as? Foo).map { foo in
      return self.bar == foo.bar
    } ?? false
  }
}
公共类Foo:equalable{
功能等同(rhs:Foo)->Bool{
//这里的基本逻辑
}
}
公共函数==(左:左,右:左)->Bool{
//检查此处的类型并调用相应的函数]
//这可能会自动完成,因为条形图重载了equalTo函数
返回左侧等速(右侧)
}
公共类酒吧:富{
公共变量栏:T?
公共初始化(barIn:T?){
self.bar=barIn
}
覆盖函数相等(rhs:Foo){
//在这里把rhs投给Foo
//如果无法完成,则返回false
return(rhs as?Foo).map{Foo-in
返回self.bar==foo.bar
}??错误
}
}

虽然我在Swift参考资料中没有找到关于这方面的任何信息

泛型的优先级较低。请记住,Swift喜欢尽可能“具体”,而泛型则不那么具体。具有非泛型参数的函数(即使是协议函数)总是优先于泛型参数:

不过,这似乎与
equalable
没有任何关系;该测试向我们展示了相同的行为:

class Foo {};
class Bar<T>: Foo {};
class Baz: Bar<Int> {};
class Qux<T>: Baz {};

func test(foo: Foo) {
    print("Foo version!");
};

func test<T>(bar: Bar<T>) {
    print("Bar version!");
};

func test(baz: Baz) {
    print("Baz version!");
};

func test<T>(qux: Qux<T>) {
    print("Qux version!");
};

let foo = Foo();
let bar = Bar<Int>();
let baz = Baz();
let baz2: Bar<Int> = Baz();
let qux = Qux<Float>();

test(foo);  // Foo
test(bar);  // Foo
test(baz);  // Baz
test(baz2); // Foo
test(qux);  // Baz
class Foo{};
类栏:Foo{};
类Baz:Bar{};
类Qux:Baz{};
func测试(foo:foo){
打印(“Foo版本!”);
};
func测试(巴:巴){
打印(“条形图版本!”);
};
func检验(baz:baz){
打印(“Baz版!”);
};
func测试(qux:qux){
印刷品(“Qux版!”);
};
设foo=foo();
设bar=bar();
设baz=baz();
设baz2:Bar=Baz();
设qux=qux();
测试(foo);//foo
测试(bar);//Foo
测试(baz);//baz
test(baz2);//Foo
测试(qux);//Baz
因此,这里发生的事情是,在选择自由函数时,除了使用其静态类型而不是动态类型,Swift更倾向于不使用任何泛型,即使泛型是一个类型参数,而且确实应该是最专门的选择


因此,似乎要解决这个问题,正如@VMAtm所建议的,您应该向类中添加一个类似
equalTo
的方法,以便在运行时提取实际的方法。

您是否使用断点或任何类型的日志来确认实际调用的方法?是的,我在我的项目中使用了断点,其中appens.调用跳过超类的==定义,尽管lhs和RH是相同的类型。上面的示例是我制作的一个玩具示例,可复制到游乐场。您可能也应该将标记
语言律师
添加到此主题。虽然这可能解决问题,但这并不能回答问题。Accordin对于Swift引用,应该调用最专门的函数,即使是静态类型,也不会发生这种情况。我可能在阅读引用时错过了一些东西……这是一个很好的解释,谢谢。你是对的,这更多的是一个关于重载函数的问题。希望苹果有这样的东西吗在他们的文档中检查过这个,明白吗