【问题标题】:Generic type with custom object in Swift languageSwift 语言中带有自定义对象的泛型类型
【发布时间】:2014-06-03 15:27:27
【问题描述】:

我想知道有没有办法在以下泛型函数中将两个泛型类型实例与== 运算符进行比较:

 func compare<T>(T a, T b) -> Bool {
    if a == b{
       // do something
       return true; 
    }else{
       // do another thing
       return false;
    }   
 }

这是我的自定义对象:

class MyObj{
  var id = 3
  var name: String?
}

【问题讨论】:

    标签: generics swift


    【解决方案1】:

    来自 Apple 开发者资源,

    并非 Swift 中的每种类型都可以与等于运算符 (==) 进行比较。例如,如果您创建自己的类或结构来表示复杂的数据模型,那么 Swift 无法为您猜到该类或结构的“等于”的含义。因此,无法保证此代码适用于所有可能的类型 T,并且当您尝试编译代码时会报告相应的错误。

    然而,一切都没有丢失。 Swift 标准库定义了一个名为
    的协议 Equatable,需要任何符合的类型来实现等于运算符 (==) 和不等于运算符 (!=) 比较该类型的任何两个值。所有的 Swift 的标准类型自动支持 Equatable 协议。

    任何 Equatable 类型都可以安全地与 findIndex 函数一起使用,因为它保证支持等于运算符。为了表达这一事实,您可以在定义函数时编写 Equatable 的类型约束作为类型参数定义的一部分:

    func findIndex<T: Equatable>(array: T[], valueToFind: T) -> Int? {
        for (index, value) in enumerate(array) {
            if value == valueToFind {
                return index
            }
        }
        return nil
    }
    

    这是他们文档中的一个示例,解释了如何覆盖 ==

    struct MyStruct: Equatable {
        var name = "Untitled"
    }
    func == (lhs: MyStruct, rhs: MyStruct) -> Bool {
        return lhs.name == rhs.name
    }
    
    let value1 = MyStruct()
    var value2 = MyStruct()
    let firstCheck = value1 == value2
    // firstCheck is true
    
    value2.name = "A New Name"
    let secondCheck = value1 == value2
    // secondCheck is false
    

    在你的情况下,你会这样做,

    class MyObj{
      var id = 3
      var name: String?
    }
    
    func == (lhs: MyObj, rhs: MyObj) -> Bool {
        return lhs.id == rhs.id
    }
    

    【讨论】:

    • 所以我必须为自己的对象实现Equatable 协议才能使其具有可比性?
    【解决方案2】:

    您可以创建自己的等价运算符 == 和 != 实现,如下所示:

    @infix func == (left: MyObj, right: MyObj) -> Bool {
        return (left.id == right.id) && (left.name == right.name)
    }
    @infix func != (left: MyObj, right: MyObj) -> Bool {
        return !(left == right)
    }
    
    var obj1 = MyObj()
    var obj2 = MyObj()
    obj1.id = 5
    obj1 == obj2 // false
    obj2.id = 5
    obj1 == obj2 // true
    
    obj1.name = "John"
    obj1 == obj2 // false
    

    【讨论】:

      【解决方案3】:

      为了使用您的通用compare() 方法,您需要使类符合Equatable protocol,然后您可以使用== 运算符(但是您可以直接调用== 运算符) ):

      import Cocoa
      
      class MyObj : Equatable {
          var id: Int = 0
          var name: String?
      }
      
      func == (lhs: MyObj, rhs: MyObj) -> Bool {
          return lhs.id == rhs.id && lhs.name? == rhs.name?
      }
      
      
      func compare<T: Equatable>(a: T, b: T) -> Bool {
          return a == b
      }
      
      var obj1 = MyObj()
      obj1.id = 12;
      obj1.name = "Andy"
      var obj2 = MyObj()
      obj2.id = 12;
      obj2.name = "Andy"
      
      if compare(obj1, obj2) {
          println("equal")
      } else {
          println("not equal")
      }
      

      【讨论】:

      • 你为什么使用比较方法?你不能只使用== 运算符进行比较吗?
      • @GokhanArik 是的,我在回答中提到了这一点。然而,看着 OP 的问题,他想在 compare() 本身内做点什么。
      • 对不起,我没注意。
      • 为什么==覆盖函数在类外?如果我有多个 equatable 类,它还能工作吗?
      猜你喜欢
      • 2018-02-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-18
      相关资源
      最近更新 更多