0

I am wondering what is wrong with the following code ?

import Foundation

enum SliderType: Int {
    case analog = 1, discrete, highLow
}

protocol DataEntry: class, Hashable {

    var hashValue: Int { get set } // hashable protocol requires this
    var idx: Int { get set }
    var category: String { get set }
    var sliderType: SliderType { get set }
    var sliderTitle: String { get set }
    var sliderCurrentValue: Float { get set }
    var sliderMinValue: Float { get set }
    var sliderMaxValue: Float { get set }
}

func ==(lhs: DataEntry, rhs: DataEntry) -> Bool {
    return lhs.idx == rhs.idx
}

As can be seen in this screenshot, I keep getting the error Protocol 'DataEntry' can only be used as a generic constraint because it has Self or associated type requirements

Does anybody know what might be wrong here ?? How do you implement a Hashable protocol to a protocol ?

enter image description here

iKK
  • 6,394
  • 10
  • 58
  • 131

1 Answers1

0

== requires the lhs and rhs be the same type. Having both be of type DataEntry isn't sufficient, as you could have the lhs be FooDataEntry, and the rhs be BarDataEntry.

You need to use generics in order to enforce this relationship between lhs and rhs.

func ==<T: DataEntry>(lhs: T, rhs: T) -> Bool {
    return lhs.idx == rhs.idx
}
Alexander
  • 59,041
  • 12
  • 98
  • 151
  • Hmm - still did not help. I keep getting the same error (i.e. `Protocol 'DataEntry' can only be used as a generic constraint because it has Self or associated type requirements`... Could it be due to the fact that I make quite some classes conform to the `DataEntry`protocol. And these might not fall under the equatable-protocol - even with your idea of introducing generics! I guess I might have to look into making equatable work for all the classes I made conform to `DataEntry`... Or do you have any other idea ? – iKK Feb 19 '17 at 20:27
  • 1
    Pretty much wherever I use `DataEntry`such as for example inside another protocol: `protocol BalancesModel { func getEntries(_ completionHandler: @escaping (_ entries: [DataEntry]) -> Void) }` or inside a class, for example - where I create a property: `fileprivate var entries = [DataEntry]()` – iKK Feb 19 '17 at 20:34
  • 1
    Well yeah, that's a consequence of using protocols with Sef/associated type requirements. Once you make `DataEntry` have a Self type requirement (which you do indirectly my making it Equatable, which has a Self type requirement), you can only ever use it as a generic constraint – Alexander Feb 19 '17 at 20:43
  • 1
    `DataEntry` isn't just one type now, it's an incomplete type. There's one version of it for every possible `Self` value it can have. Allowing you to use it directly as a type would allow you, for example, to take two different `DataEntry` subtypes and try to compare them. The equality operator is only defined for two objects of the same type, so this wouldn't be defined. – Alexander Feb 19 '17 at 20:44
  • Thank you, I guess the "every possible Self" part is the tricky one, isn't it? I need to think of what I will do next. Thanks for your support! – iKK Feb 19 '17 at 20:52