믹스인

Mixin

오브젝트 지향 프로그래밍 언어에서 믹스인(또는 [1][2][3][4]믹스인)은 다른 클래스의 부모 클래스일 필요 없이 다른 클래스에서 사용하는 메서드를 포함하는 클래스입니다.이러한 다른 클래스가 믹스인의 메서드에 액세스하는 방법은 언어에 따라 다릅니다.믹스인은 "상속"이 아니라 "포함"으로 표현될 수 있습니다.

믹스인은 코드 재사용을 장려하며 여러 상속으로 인해 발생할 수 있는[5] 상속 모호성(다이아몬드 문제)을 방지하거나 언어에서 여러 상속을 지원하지 않는 문제를 해결하기 위해 사용할 수 있습니다.믹스인은 구현된 메서드를 가진 인터페이스로도 볼 수 있습니다.이 패턴은 의존성 반전 원칙을 적용하는 예입니다.

역사

Mixins는 심볼릭스의 객체 지향 플레이버 시스템(Howard Cannon이 개발)에서 처음 등장했는데, 이는 리스프 머신 리스프에서 사용되는 객체 지향 접근법이었다.이 이름은 [1]매사추세츠주 서머빌에 있는 스티브 아이스크림 판매소에서 영감을 받았습니다.아이스크림 가게의 주인은 기본적인 맛의 아이스크림(바닐라, 초콜릿 등)을 제공하고 여분의 아이템(너트, 쿠키, 퍼지 등)을 혼합하여 제공했으며 [2]그 제품을 당시 그의 상표인 "믹스인"이라고 불렀다.

정의.

믹스인은 프로그래머가 클래스에 일부 코드를 주입할 수 있는 언어 개념입니다.믹스인 프로그래밍은 소프트웨어 개발의 한 스타일로, 기능 단위가 클래스에서 생성되어 다른 [6]클래스와 혼합됩니다.

mixin 클래스는 원하는 기능을 포함하는 부모 클래스로 기능합니다.서브클래스는 이 기능을 상속하거나 단순히 재사용할 수 있지만 전문화 수단으로는 사용할 수 없습니다.일반적으로 믹스인은 단일 "is a" 관계를 확립하지 않고 원하는 기능을 하위 클래스로 내보냅니다.여기서 믹스인과 상속의 개념 사이에 중요한 차이가 있습니다.자녀 클래스는 부모 클래스의 모든 기능을 상속할 수 있지만, 부모가 되는 것에 대한 의미론은 반드시 적용할 필요는 없습니다.

이점

  1. 하나의 클래스가 여러 클래스의 공통 기능을 사용할 수 있도록 함으로써 여러 [7]상속의 복잡한 의미론을 사용하지 않도록 함으로써 여러 상속을 위한 메커니즘을 제공합니다.
  2. 코드 재사용성: 믹스인은 프로그래머가 다른 클래스 간에 기능을 공유하고 싶을 때 유용합니다.같은 코드를 반복해서 반복하는 것이 아니라 공통 기능을 단순히 믹스인으로 그룹화하여 필요한 [8]각 클래스에 포함시킬 수 있습니다.
  3. mixin을 사용하면 부모 [9]클래스의 모든 기능이 아닌 부모 클래스의 원하는 기능만 상속 및 사용할 수 있습니다.

실장

Simula에서 클래스는 속성, 메서드 및 클래스 초기화가 모두 함께 정의되는 블록에 정의되므로 클래스에서 호출할 수 있는 모든 메서드가 함께 정의되고 클래스의 정의가 완료됩니다.

플레이버에서 믹스인은 다른 클래스가 슬롯 정의 및 메서드를 상속할 수 있는 클래스입니다.일반적으로 믹스인에는 직접 인스턴스가 없습니다.플레이버는 여러 다른 플레이버에서 상속할 수 있으므로 1개 이상의 믹스인에서 상속할 수 있습니다.원래의 플레이버는 범용 기능을 사용하지 않았습니다.

New Flavors(Flavors의 후속 버전) CLOS에서 메서드는 "일반 기능"으로 구성됩니다.이러한 범용 함수는 클래스 디스패치 및 메서드 조합에 의해 여러 케이스(메서드)로 정의되는 함수입니다.

CLOS 및 플레이버에서는 mixin 메서드를 사용하여 기존 메서드에 동작을 추가할 수 있습니다.:before그리고.:after데몬, 와퍼, 랩퍼, 플레이버.CLOS 추가:aroundschaded 메서드를 호출할 수 있습니다.CALL-NEXT-METHOD예를 들어 stream-lock-mixin은 스트림클래스의 기존 메서드에 잠금을 추가할 수 있습니다.Flavors 에서는 랩퍼 또는 와퍼를 쓰고 CLOS 에서는 wapper를 사용합니다.:around방법.CLOS와 플레이버는 모두 메서드의 조합을 통해 계산된 재사용이 가능합니다. :before,:after그리고.:around메서드는 표준 메서드 조합의 기능입니다.기타 메서드 조합이 제공됩니다.

예를 들어,+method combination : 일반 함수의 적용 가능한 각 method의 결과값을 산술적으로 가산하여 반환값을 계산합니다.예를 들어 그래픽 객체의 경계 혼합과 함께 사용됩니다.그래픽 오브젝트는 범용 너비 함수를 가질 수 있다.border-mixin은 객체 주위에 경계선을 추가하고 너비를 계산하는 방법을 가지고 있습니다.새로운 클래스bordered-button(그것은 그래픽 오브젝트이며,bordermixin)은 모든 적용 가능한 폭 메서드를 호출하여 폭을 계산합니다.+메서드의 조합.모든 반환값이 추가되고 객체의 결합된 너비가 생성됩니다.

OPSLA [10]90 논문에서 Gilad Bracha와 William Cook은 Smalltalk, Beta 및 CLOS에서 발견되는 다양한 상속 메커니즘을 혼합 상속의 특수한 형태로 재해석했습니다.

믹스인을 사용하는 프로그래밍 언어

Flavors 및 CLOS(Common Lisp의 일부) 이외에 믹스인을 사용하는 언어는 다음과 같습니다.

일부 언어에서는 언어 수준에서 믹스인을 지원하지 않지만 실행 시 오브젝트 간에 메서드를 복사하여 쉽게 모방할 수 있으며, 이로 인해 믹스인의 메서드를 "차용"할 수 있습니다.이는 정적으로 입력된 언어에서도 가능하지만 확장된 메서드 집합을 사용하여 새 개체를 구성해야 합니다.

믹스인을 지원하지 않는 다른 언어들은 다른 언어구조를 통해 이들을 우회적으로 지원할 수 있습니다.예를 들어 Visual Basic과 같이 입력합니다.NET 및 C#은 인터페이스에 확장 메서드의 추가를 지원합니다.즉, 확장 메서드가 정의된 인터페이스를 구현하는 클래스는 모두 의사 멤버로서 확장 메서드를 사용할 수 있습니다.

공통 리스프

Common Lisp는 플레이버와 마찬가지로 CLOS(Common Lisp Object System)에 믹스인을 제공합니다.

object-width1개의 인수를 가진 범용 함수입니다.+메서드의 조합.이 조합에 따라 일반 함수에 해당하는 모든 메서드가 호출되고 결과가 추가됩니다.

(디제너릭 오브젝트 폭 (물건)   (: 콤비네이션 +)) 

button는 버튼 텍스트용 슬롯이 1개 있는 클래스입니다.

(디클래스 단추 ()   ((본문 : 초기화 "클릭"))) 

클래스 버튼 객체에는 버튼 텍스트의 길이에 따라 너비를 계산하는 방법이 있습니다. +는 같은 이름의 메서드 조합의 메서드 한정자입니다.

(디프로덕트 오브젝트 폭 + ((물건 단추))    (* 10 (길이 (슬롯 값 물건 '텍스트)))) 

A border-mixin수업 이름 짓기는 규칙일 뿐이야슈퍼클래스도 슬롯도 없습니다.

(디클래스 경계에 끼다 () ()) 

테두리 폭을 계산하는 방법이 있습니다.여기 4개밖에 없어요.

(디프로덕트 오브젝트 폭 + ((물건 경계에 끼다))   4) 

bordered-button클래스가 양쪽에서 상속되는 경우border-mixin그리고.button.

(디클래스 테두리 단추 (경계에 끼다 단추) ()) 

이제 단추의 너비를 계산할 수 있습니다.부르기object-width80을 계산합니다.결과는 적용 가능한 단일 방법인 method의 결과입니다.object-width반을 위해서button.

? (오브젝트 폭 (제조법 '버튼)) 80 

또, 1의 폭도 계산할 수 있습니다.bordered-button.부르기object-width84를 계산합니다.결과는 적용 가능한 두 가지 방법, 즉 method의 결과의 합입니다.object-width반을 위해서button및 방법object-width반을 위해서border-mixin.

? (오브젝트 폭 (제조법 '버튼')) 84 

Python의 경우

Python에서는 mixin 개념의 예를 다음에 나타냅니다.SocketServer모듈([17]양쪽 모두 포함)UDPServer클래스 및 aTCPServer각각 UDP 및 TCP 소켓서버의 서버로서 기능합니다.또한 다음 두 가지 혼합 클래스가 있습니다.ForkingMixIn그리고.ThreadingMixIn보통 새로운 접속은 모두 같은 프로세스 내에서 처리됩니다.확장으로TCPServer와 함께ThreadingMixIn다음과 같습니다.

학급 스레드화TC 서버(스레딩 믹스인, TC 서버):     통과하다 

ThreadingMixInclass는 TCP 서버에 기능을 추가하여 새로운 연결마다 새로운 스레드를 만듭니다.같은 방법을 사용하여ThreadingUDPServer코드를 복제하지 않고 생성할 수 있습니다.ThreadingMixIn. 또는,ForkingMixIn새로운 접속마다 프로세스가 분기됩니다.새 스레드를 만들거나 프로세스를 분기하는 기능은 독립형 클래스로서는 그다지 유용하지 않습니다.

이 사용 예에서는 믹스인은 소켓서버로서의 기능에 영향을 주지 않고 대체 기본 기능을 제공합니다.

인루비

대부분의 Ruby World는 Mixin을 기반으로 합니다.Modulesmixins의 개념은 키워드로 Ruby에서 구현됩니다.include모듈 이름을 파라미터로 전달합니다.

예:

학급 학생입니다   포함하다 동등한 # 클래스 학생은 'include' 키워드를 사용하여 비교 가능한 모듈을 상속합니다.   attr_accessor : 이름, : 스코어    방어하다 초기화하다(이름., 스코어)     @name = 이름.     @점수 = 스코어   끝.    # Comparable 모듈을 포함하려면 구현 클래스가 <=> 비교 연산자를 정의해야 합니다.   # 여기 비교 연산자가 있습니다.우리는 점수를 바탕으로 두 학생의 사례를 비교합니다.    방어하다 <=>(다른.)     @점수 <=> 다른..스코어   끝.    # 좋은 점은 다음과 같습니다.<, <=, >= 및 기타 Comparable Interface 메서드에 무료로 액세스 할 수 있습니다. 끝.  s1 = 학생입니다.신규('피터', 100) s2 = 학생입니다.신규('제이슨', 90)  s1 > s2 #진짜 s1 <=> s2 #false(거짓말) 

자바스크립트

오브젝트 리터럴과 어프로치

오브젝트 내의 키에 함수를 바인드함으로써 오브젝트에 동작을 추가할 수 있습니다.단, 스테이트와 동작을 분리하지 않으면 다음과 같은 단점이 있습니다.

  1. 모델 도메인의 속성과 구현 도메인의 속성을 혼합합니다.
  2. 일반적인 행동을 공유할 수 없습니다.메타 객체는 개체의 도메인별 속성을 동작별 속성에서 [18]분리하여 이 문제를 해결합니다.

확장 함수는 동작을 다음과 [19]같이 혼합하기 위해 사용됩니다.

'엄밀하게 사용';  컨스턴트 하프링 = 기능. (fName(fName), 이름) {   이것..이름 = fName(fName);   이것.. = 이름; };  컨스턴트 혼재 = {   풀네임() {     돌아가다 이것..이름 + ' ' + 이것..;   },   이름을 바꾸다(첫번째, 지난) {     이것..이름 = 첫번째;     이것.. = 지난;     돌아가다 이것.;   } };  // 확장 함수 컨스턴트 확장하다 = (obj, 혼재) => {   물건.열쇠들.(혼재).각각(열쇠 => obj[열쇠] = 혼재[열쇠]);   돌아가다 obj; };  컨스턴트 샘. = 신규 하프링(, '로리'); 컨스턴트 프로도 = 신규 하프링('자유', '백');  // 다른 메서드 혼재 확장하다(하프링.시제품, 혼재);  콘솔.로그.(샘..풀네임());  // 샘 로리 콘솔.로그.(프로도.풀네임());  // 프리다 백스  샘..이름을 바꾸다('샘와이즈', 갬지); 프로도.이름을 바꾸다('개구리', '배긴스');  콘솔.로그.(샘..풀네임());  // 샘와이즈 갬지 콘솔.로그.(프로도.풀네임());  // 프로도 배긴스 

Object.assign()을 사용한 혼재

'엄밀하게 사용';  // 객체 생성 컨스턴트 obj1 = {   이름.: 마르쿠스 아우렐리우스,   도시: '로미',   태어난: '121-04-26' };  // 믹스인 1 컨스턴트 믹스 1 = {   문자열() {     돌아가다 `${이것..이름.}에 태어났다.${이것..도시}${이것..태어난}`;   },   나이() {     컨스턴트 연도 = 신규 날짜.().만년();     컨스턴트 태어난 = 신규 날짜.(이것..태어난).만년();     돌아가다 연도 - 태어난;   } }; // 믹스인 2 컨스턴트 믹스2 = {   문자열() {     돌아가다 `${이것..이름.}-${이것..도시}-${이것..태어난}`;   } };  // Object.assign()을 사용하여 mixin에서 객체에 메서드 추가 물건.할당하다(obj1, 믹스 1, 믹스2);  콘솔.로그.(obj1.문자열());   // 마르쿠스 아우렐리우스 - 로마 - 121-04-26 콘솔.로그.("그의 나이는"${obj1.나이()}금일부로);  // 오늘 현재 그의 나이는 1897년입니다. 

순수 기능 및 위임 기반 비행-혼합 접근법

첫 번째 접근방식은 대부분 널리 보급되어 있지만 다음 접근방식은 기본적으로 JavaScript 언어 코어가 제공하는 위임에 가깝습니다.

2개의 기능 객체 기반 패턴은 이미 서드파티에 의해 구현되지 않고 기능하고 있습니다.extend.

'엄밀하게 사용';  // 실장 컨스턴트 Enumerable First Last( 열거형 퍼스트 라스트) = (기능. () { // 함수 기반 모듈 패턴.   컨스턴트 첫번째 = 기능. () {       돌아가다 이것.[0];     },     지난 = 기능. () {       돌아가다 이것.[이것..길이 - 1];     };   돌아가다 기능. () {      // 함수 기반 Flight-Mixin 메커니즘...     이것..첫번째  = 첫번째;  // ...을 참조...     이것..지난   = 지난;   // 공유 코드.   }; }());  // 응용 프로그램 - 명시적 위임: // [첫 번째] 및 [마지막] 열거형 동작을 [Array]의 [protype]에 적용합니다. Enumerable First Last( 열거형 퍼스트 라스트).불러(어레이.시제품);  // 이제 다음을 수행할 수 있습니다. 컨스턴트 a = [1, 2, 3]; a.첫번째(); // 1 a.지난();  // 3 

기타 언어

Curl Web-Content 언어에서는 여러 상속이 클래스로 사용되며 인스턴스가 메서드를 구현할 수 없습니다.일반적인 믹스인에는 스키너블이 모두 포함되어 있습니다.ControlUI에서 상속되다SkinnableControlUI, 사용자 인터페이스는 StandardBaseDropdown에서 상속되는 드롭다운메뉴가 필요한 개체를 위임합니다.UI 및 명시적으로 명명된 mixin 클래스:FontGraphicMixin,FontVisualMixin그리고.NumericAxisMixin-ofclass. 버전 7.0에서는 라이브러리 액세스가 추가되어 믹스인이 같은 패키지에 포함되거나 공개 추상일 필요가 없습니다.컬 컨스트럭터는 인터페이스 또는 믹스인을 [citation needed]명시적으로 선언하지 않고 다중 상속을 쉽게 사용할 수 있는 공장입니다.

인터페이스 및 특성

Java 8에서는 인터페이스의 [20]디폴트 방식 형식으로 새로운 기능이 도입되었습니다.기본적으로 인터페이스 클래스 프로그래밍 셋업이 완료된 후 인터페이스에 새로운 메서드가 추가되는 시나리오에서 응용 프로그램이 있는 인터페이스에서 메서드를 정의할 수 있습니다.인터페이스에 새로운 기능을 추가하는 것은 인터페이스를 사용하는 모든 클래스에서 메서드를 구현하는 것을 의미합니다.디폴트 메서드는 인터페이스에 언제든지 도입할 수 있고, 관련된 클래스에서 사용되는 구현된 구조를 가지고 있는 경우에 도움이 됩니다.따라서 디폴트 메서드에서는 개념을 믹스인 방식으로 적용할 수 있습니다.

애스펙트 지향 프로그래밍과 결합된 인터페이스는 C#이나 Java와 같은 이러한 기능을 지원하는 언어로 본격적인 믹스인을 생성할 수도 있습니다.또한 마커 인터페이스 패턴, 범용 프로그래밍 및 확장 메서드를 사용하여 C# 3.0은 믹스인을 모방할 수 있습니다.C# 3.0에서는 확장 메서드가 도입되어 클래스뿐만 아니라 인터페이스에도 적용할 수 있습니다.확장 메서드는 클래스를 변경하지 않고 기존 클래스에 추가 기능을 제공합니다.그 후 확장 방식을 정의하는 특정 기능의 스태틱도우미 클래스를 작성할 수 있게 됩니다.클래스는 인터페이스를 구현하기 때문에(실제 인터페이스에 구현하는 메서드나 속성이 없는 경우에도) 모든 확장 메서드도 픽업합니다.[3][4][21]C# 8.0 에는 디폴트인터페이스 [22]방식의 기능이 추가되어 있습니다.

ECMAScript(대부분의 경우 JavaScript로 구현됨)는 필드를 한 개체에서 다른 개체로 단계적으로 복사하여 개체 구성을 모방할 필요가 없습니다.기본적으로[23] 추가 동작을 구현하고 다음으로 위임하는 함수 객체를 통해 특성 및 믹스인[24][25] 기반 객체 구성을 지원합니다.call또는apply이러한 새로운 기능을 필요로 하는 오브젝트로 이동합니다.

인스칼라

Scala는 풍부한 타입의 시스템을 갖추고 있으며 특성은 믹스인 동작을 구현하는 데 도움이 됩니다.이름에서 알 수 있듯이 특성은 일반적으로 구체적인 유형 또는 적어도 특정 [26]인스턴스의 책임과 직교하는 뚜렷한 특징 또는 측면을 나타내기 위해 사용됩니다.예를 들어, 노래하는 능력은 직교 기능으로 모델링됩니다. 새, 사람 등에 적용될 수 있습니다.

특성 가수.{   방어하다 불러보았다 { 인쇄("노래...") }   //기타 메서드 }  학급  확장 가수. 

여기서 Bird는 클래스 Bird가 메서드 sing()을 스스로 정의한 것처럼 특성의 모든 메서드를 자체 정의로 혼합했습니다.

~하듯이extends특성의 경우 슈퍼클래스로부터 물려받는데도 사용된다.extends슈퍼클래스가 상속되지 않고 첫 번째 특성에서의 믹스인에 대해서만 사용됩니다.키워드 사용에는 다음 특성이 모두 혼재되어 있습니다.with.

학급 사람인 학급 배우. 확장 사람인 와 함께 가수. 학급 배우. 확장 가수. 와 함께 퍼포먼스 

Scala를 사용하면 클래스의 새 인스턴스를 만들 때 특성을 혼합할 수 있습니다(익명 유형 생성).Person 클래스 인스턴스의 경우 모든 인스턴스가 노래할 수 있는 것은 아닙니다.이 기능은 다음과 같이 사용됩니다.

학급 사람인{   방어하다 말하다 {  인쇄 ("인간") }   //기타 메서드 }   노래하는 사람 = 신규 사람인 와 함께 가수. 노래하는 사람.불러보았다 

녹슬어 있음

녹은 특성을 통해 혼합물을 광범위하게 사용합니다.Scala와 같은 특성을 통해 사용자는 정의된 유형에 대한 행동을 구현할 수 있습니다.또한 제네릭과 다이내믹 디스패치에도 사용됩니다.이것에 의해, 같은 특성을 가지는 타입을 런타임에 각각 [27]정적으로 또는 동적으로 교환해 사용할 수 있습니다.

// 유형이 "말하기" 허용 특성 말하다 {  fn 말하다();   // Rust를 통해 구현자는 특성에 정의된 기능의 기본 구현을 정의할 수 있습니다.  fn 환영하다() {   프린트!("안녕!")  } }  구조 ;  함축하다 말하다 위해서  {  fn 말하다() {   프린트!('우우우우');  } }  구조 로봇;  함축하다 말하다 위해서 로봇 {  fn 말하다() {   프린트!("삐삐삐삐");  }   // 여기서는 Speak::great on Dog의 정의를 덮어씁니다.  fn 환영하다() {   프린트!("로봇이 하디!")  } } 

인스위프트

Mixin은 Swift에서 Protocol Extension의 Default implementation이라는 언어 기능을 사용하여 실행할 수 있습니다.

프로토콜 오류 표시 가능 {     기능하다 에러(메세지:스트링) }  확장 오류 표시 가능 {     기능하다 에러(메세지:스트링) {         // 오류를 표시하기 위해 필요한 작업을 수행합니다.         //...         인쇄물(메세지)     } }  구조 네트워크 매니저 : 오류 표시 가능 {     기능하다 온에러() {         에러("인터넷 연결을 확인하십시오.")     } } 

「 」를 참조해 주세요.

레퍼런스

  1. ^ a b Python과의 믹스인 사용
  2. ^ a b Mix-Ins (Steve's ice cream, 보스턴, 1975년)웨이백 머신에 2007-10-26 아카이브 완료
  3. ^ a b C# 확장 방식을 사용한 믹스인 구현
  4. ^ a b 정답을 알고 있습니다(42개).Mix-in과 C#
  5. ^ Boyland, John; Giuseppe Castagna (26 June 1996). "Type-Safe Compilation of Covariant Specialization: A Practical Case". In Pierre Cointe (ed.). ECOOP '96, Object-oriented Programming: 10th European Conference. Springer. pp. 16–17. ISBN 9783540614395. Retrieved 17 January 2014.
  6. ^ http://c2.com/cgi/wiki?MixIn
  7. ^ "Working with Mixins in Ruby". 8 July 2015.
  8. ^ http://naildrivin5.com/blog/2012/12/19/re-use-in-oo-inheritance.html
  9. ^ "Archived copy". Archived from the original on 2015-09-25. Retrieved 2015-09-16.{{cite web}}: CS1 maint: 제목으로 아카이브된 복사(링크)
  10. ^ OOPSLA '90, Mixin 기반 상속(pdf)
  11. ^ Bill Wagner. "Create mixin types using default interface methods". docs.microsoft.com. Retrieved 2022-04-18.
  12. ^ slava (2010-01-25). "Factor/Features/The language". concatenative.org. Retrieved 2012-05-15. Factor's main language features: … Object system with Inheritance, Generic functions, Predicate dispatch and Mixins {{cite web}}:외부 링크 publisher=(도움말)
  13. ^ Alain Frisch (2013-06-14). "Mixin objects". LexiFi. Retrieved 2022-03-29.
  14. ^ "Classes - MATLAB & Simulink - MathWorks India".
  15. ^ "Mixin Class Composition". École polytechnique fédérale de Lausanne. Retrieved 16 May 2014.
  16. ^ XOTcl에서의 Mixin 클래스
  17. ^ CPython 3.5의 SocketServer 소스 코드
  18. ^ "Mixins, Forwarding, and Delegation in JavaScript".
  19. ^ "Archived copy". Archived from the original on 2015-09-21. Retrieved 2015-09-16.{{cite web}}: CS1 maint: 제목으로 아카이브된 복사(링크)
  20. ^ "Default Methods (The Java™ Tutorials > Learning the Java Language > Interfaces and Inheritance)".
  21. ^ C#의 믹스인, 제네릭 및 확장 방식
  22. ^ 기본 인터페이스 메서드를 사용하여 인터페이스를 사용하여 클래스를 만들 때 기능 혼합
  23. ^ 특성혼합과 같은 역할 지향 프로그래밍 접근 방식을 일반화하기 위한 JavaScript의 많은 재능, 2014년 4월 11일.
  24. ^ Angus Croll, JavaScript Mixins의 새로운 개요, 2011년 5월 31일 발행.
  25. ^ JavaScript 코드 재사용 패턴, 2013년 4월 19일.
  26. ^ "Scala in practice: Traits as Mixins – Motivation". 19 July 2009.
  27. ^ "Traits: Defining Shared Behavior - the Rust Programming Language".

외부 링크