- This topic has 4개 답변, 3명 참여, and was last updated 4 years, 8 months 전에 by i참.
2 답변 글타래를 보이고 있습니다
-
글쓴이글
-
-
i참참가자
- 글작성 : 1
- 답글작성 : 10
공통으로 사용하는 UI 컴포넌트들은 아래와 같이 템플릿을 만들어 사용하곤 했는데요. 어제 갑자기 bind 메소드를 오버라이드 하는 부분에서 컴파일 에러가 발생했습니다(Xcode 11.4 beta). 분명 멀쩡히 빌드가 되었었는데 말이죠(Xcode 11.3.1).
import UIKit class BaseTableViewCell: UITableViewCell { override func prepareForReuse() { self.gestureRecognizers?.removeAll() } override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) selectionStyle = .none setupView() } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } func bind<T>(content: T) {} func setupView() {} }
class EventMapCell: BaseTableViewCell { //❗️Overridden method 'bind' has generic signature <T where T : EventMapCell.Content> Which is incompatible with base method's generic signature <T>; expected generic signature to be <T> override func bind<T: Content>(content: T) { ... } } extension EventMapCell { strcut Content { ... } }
컴파일러의 버그인 줄 알았지만 아니었습니다. Swift 5.2에서 변경되는 부분이었습니다(확인을 도와준 라이노에게 감사감사).
- Xcode 11.4 Beta 3 Release Notes
A method override can no longer have a generic signature with requirements not imposed by the base method. For example, the below code produces an error. (23626260) (FB5382462)
protocol P {} class Base { func foo<T>(arg: T) {} } class Derived: Base { // generates an error because of the added requirement override func foo<T: P>(arg: T) {} }
처음엔 ‘이것도 되나? 되는구나!’ 하고 넘어갔는데 말입니다. 사실은 위험한 코드였습니다. 스위프트 포럼에서 간단한 예시를 가져왔습니다.
- class A는 프로토콜 P와 Q를 준수하는 타입 T를 인자로 사용하는 메소드 foo를 가집니다.
- class B는 A를 상속받고, 메소드 foo를 오버라이드하여 프로토콜 P, Q, R을 모두 준수하도록 하고 있습니다.
- 프로토콜 P와 Q를 준수하는 객체 C를, A타입의 객체 B의 foo 메소드 인자로 넘겨 실행하면 class A가 R을 채택하지 않았기 때문에 런타임에
BAD ACCESS
에러가 발생합니다.
public protocol P {} public protocol Q {} public protocol R { func r() } //1 open class A { open func foo<T: P & Q>(arg: T) {} } //2 open class B: A { open override func foo<T: P & Q & R>(arg: T) { arg.r() } } //3 class C: P, Q {} let a: A = B() a.foo(arg: C())
컴파일 타임에 타입 체크가 다 되는 줄 알았는데 버그였습니다. 리스코프 치환 원칙 위반이기도 하구요. 더 쓰려했는데 퇴근시간이 다가와서 이만 줄입니다. 즐거운 한 주 보내세요??
참고
2020-03-09 오후 4:08 #2599 -
-
-
-
글쓴이글
2 답변 글타래를 보이고 있습니다
- 답변은 로그인 후 가능합니다.