2017-08-31 103 views
2

我有一个EquatableAnyObject尝试转换为Equatable

class Item: Equatable { 
    var value: AnyObject? 
    var title: String 
    init(title: String, value: AnyObject?) { 
     self.title = title 
     self.value = value 
    } 
    //Equatable 
    public static func ==(lhs: Item, rhs: Item) -> Bool { 
     return ((lhs.title == rhs.title) && (lhs.value === rhs.value)) 
    } 
} 

但我想投试无功value到Equatable,这样拿到手软equatable结果

if let lValue = lhs.value as? Equatable, // Error 
    let rValue = rhs.value as? Equatable { // Error 
    valueEq = (lValue == rValue) 
} else { 
    valueEq = (lhs.value === rhs.value) 
} 

此代码捕获编译错误关于通用Equatable

我怎么样我可以做正确的对于这个班的Equatable?

UPD

我想用我的ItemUITableViewCell在我的故事板。我不能创建通用的UITableViewCell。如果我尝试做的项目为Generic<T: Equatable>类,我将不得不在我的细胞对指定类型,

var items: [Item<OnlyThisHashableClass>] 

但我想使用细胞项目的任何对象

+0

你的代码为您发布什么问题? – rmaddy

+1

您需要创建一个符合Equatable的自定义值类型。 –

+0

用确切完整的错误信息更新您的问题,而不是一些总结。 – rmaddy

回答

1

简单的方法 - 类留非泛型,通用只有init,并在GenericInit创建isEquals方法

class FieldItem: CustomStringConvertible, Equatable { 
    let value: Any? 
    let title: String 
    private let equals: (Any?) -> Bool 
    init<Value: Equatable>(title: String, value: Value?) { 
     func isEquals(_ other: Any?) -> Bool { 
      if let l = value, let r = other { 
       if let r = r as? Value { 
        return l == r 
       } else { 
        return false 
       } 
      } else { 
       return true 
      } 
     } 
     self.title = title 
     self.value = value 
     self.equals = isEquals 
    } 
    //CustomStringConvertible 
    var description: String { get { return title } } 
    //Equatable 
    public static func ==(lhs: FieldItem, rhs: FieldItem) -> Bool { 
     return ((lhs.title == rhs.title) && lhs.equals(rhs.value)) 
    } 

} 
1

你可以不投AnyObject到一个Equatable

你可以做的是定义Item作为通用为其valueWrapped,必须Equatable

class Item<Wrapped: Equatable> { 
    var title: String 
    var value: Wrapped 

    init(title: String, value: Wrapped) { 
     self.title = title 
     self.value = value 
    } 
} 

extension Item: Equatable { 
    static func ==(lhs: Item, rhs: Item) -> Bool { 
     return lhs.title == rhs.title && lhs.value == rhs.value 
    } 
} 

而且,让我们假设你有一些类,Foo,即(一)ISN”可以等同的; (b)是你想包装在Item;和(c)你真的想要在身份运算符===的基础上将它们定义为equatable。 (我承认,我发现这个概念,你称之为“软等于”相当令人不安的概念,但我不会在这里进入这一点。)

无论如何,你可以使你的类Foo equatable的基础上身份操作:

extension Foo: Equatable { 
    static func ==(lhs: Foo, rhs: Foo) -> Bool { 
     return lhs === rhs 
    } 
} 

或者,如果你需要为很多类做到这一点,你甚至可以为这个身份平等的协议,然后你的非equatable类可能只是符合是:

protocol IdentityEquatable: class, Equatable { } 

extension IdentityEquatable { 
    static func ==(lhs: Self, rhs: Self) -> Bool { 
     return lhs === rhs 
    } 
} 

然后,你想要wr的任何类AP在ItemEquatable可以采取与每个代码一行这个身份equatable行为:

extension Foo: IdentityEquatable { } 
extension Bar: IdentityEquatable { } 
extension Baz: IdentityEquatable { } 

顺便说一句,SE-0143已获批准,而不是语言的一部分,但,提供条件一致性的未来斯威夫特版本的承诺,即:

class Item<Wrapped> { 
    var title: String 
    var value: Wrapped 

    init(title: String, value: Wrapped) { 
     self.title = title 
     self.value = value 
    } 
} 

extension Item: Equatable where Wrapped: Equatable { 
    static func ==(lhs: Item, rhs: Item) -> Bool { 
     return lhs.title == rhs.title && lhs.value == rhs.value 
    } 
} 

在这种情况下,ItemEquatable当且仅当该Wrapped VAL你是Equatable。这不是该语言的一部分,但看起来像将在未来的版本。这是一个优雅的解决方案(虽然不是,不可否认,你的“软等值”思想)。

+0

但我在许多类中使用我的'Item',例如在故事板中的'UITableViewCell'中。如果我尝试将'Item'作为Generic类,我将被迫指定单元格中的类型,但是我希望使用Cells中的Item作为基类(值 - AnyObject) –

相关问题