[Swift] - Hashable 관련 이슈
protocol can only be used as a generic constraint becaues it has Self or associated type requirements
Hashable을 상속한 프로토콜 안의 멤버 변수의 타입을 또 hashable을 상속한 프로토콜로 설정했더니 아래와 같은 에러가 떴다.
Protocol '' can only be used as a generic constraint because it has Self or associated type requirements
그니까 프로토콜이 Self / associated type 요구사항을 가지고 있기 때문에 generic constraint로만 사용될 수 있다는 것이다.
예시 코드를 작성해봤다.
protocol Animal {
var name: String { get }
var age: Int { get }
var owner: Owner { get }
}
final class AnimalClass: Animal {
let name: String
let age: Int
let owner: Owner
init(name: String, age: Int, owner: Owner) {
self.name = name
self.age = age
self.owner = owner
}
}
protocol Owner {
var name: String { get }
var address: String { get }
}
final class OwnerClass: Owner {
let name: String
let address: String
init(name: String, address: String) {
self.name = name
self.address = address
}
}
요 상황에서, Animal이 hashable을 상속하게 해보았다. Hashable 프로토콜은 Equatable 프로토콜을 상속하고 있기 때문에, Hashable 프로토콜을 상속하면 Equatable 프로토콜의 요구사항도 만족해야 한다.
이러면 아직 Owner 프로토콜은 아직 Hashable을 상속받고 있지 않기 때문에 에러가 또 발생하는 것을 볼 수 있다. 이를 해결하기 위해 Owner 프로토콜이 Hashable을 따르도록 수정해보았다.
이러면 이제 Animal 프로토콜과 클래스 쪽에서 이런 에러를 볼 수 있다.
관련해서 StackOverflow 글을 참고해서 뭐가 문제인지 찾아봤다.
설명에 의하면 Hashable
프로토콜은 Equatable
프로토콜을 따르고 있고, Equatable
프로토콜은 아래의 요구사항을 가지고 있다.
func ==(lhs: Self, rhs: Self) -> Bool
그리고 이런 Self
를 자기 자신 안에서 가진 프로토콜은 type constraint를 제외하고 사용할 수 없기 때문에 이런 에러가 발생한는 것이다. 그렇다면 왜 Self
나 associated type을 가진 프로토콜은 type constraint에서만 사용이 가능한 것일까?
아래와 같은 프로토콜이 있다고 가정해보자.
protocol SomeType: class {
associatedtype Model
func doSomethingWithModel(model: Model)
}
그리고 아래와 같은 메서드를 구현했다고 해보자.
func doSomethingWithTypes(types: [SomeType]) {
for type in types {
type.doSomethingWithModel(//여기에 어떤 타입의 argument가 전달됐는지 알아야 하는데, 그것이 모호하다)
}
}
Swift는 이런 모호함을 좋아하지 않기 때문에 associated type을 가진 프로토콜로 변수를 선언하는 것을 허용하지 않는다.