trait 메서드가 추상적일 필요는 없어. trait 안에 바로 기본 구현 을 줄 수 있고, 타입들은 override 안 하면 공짜로 그걸 얻어.
공짜 동작
trait 정의에 본문을 주면 모든 구현자가 아무것도 안 쓰고 그걸 물려받아. 타입은 커스텀 동작이 필요하면 여전히 기본을 override 할 수 있고. 이게 trait 이 구현자한테 작은 코어만 쓰게 요구하면서 풍부한 API 를 제공하는 방식이야.
필수 메서드를 부르는 기본 메서드
강력한 수: 기본 메서드가 같은 trait 의 다른 메서드를 부를 수 있어 — 기본 없는 것까지. 그래서 구현자한테 작은 메서드 하나를 제공하라 요구하고, trait 이 그 위에 동작 한 무리를 지어. 표준 라이브러리 Iterator 가 정확히 이렇게 작동해: next 를 구현하면 수십 개 메서드 (map, filter, sum...) 를 공짜로 얻어.
조금 요구하고, 많이 제공해. 최고의 trait 설계는 구현자한테 최소 코어 메서드를 요구하고, 그 위에 기본 메서드를 쌓아.
Iterator 는 next() 만 요구하고 그 위에 지은 70+ adapter 메서드를 건네줘. 네 trait 도 같은 식으로 설계해.왜 이게 상속을 이기냐
클래스 기반 언어에선 base class 를 상속해서 공유 동작을 얻어 — 그 데이터랑 계층 속 자리를 끌고 오면서. 기본 trait 메서드는 그 결합 없이 공유 동작 을 줘: 어디의 어떤 타입이든 trait 에 옵트인해서 기본을 얻어, 가계도에 강제로 들어가지 않고.