전송(개체 지향 프로그래밍)

Forwarding (object-oriented programming)

오브젝트 지향 프로그래밍에서 포워딩이란 오브젝트(속성 또는 메서드)의 멤버를 사용함으로써 실제로 다른 오브젝트의 대응하는 멤버를 사용하는 것을 의미합니다.사용은 다른 오브젝트로 포워딩됩니다.포워딩은 여러 설계 패턴에서 사용됩니다.여기서 일부 멤버는 다른 오브젝트로 전송되고 다른 멤버는 직접 사용되는 오브젝트에 의해 처리됩니다.포워딩 오브젝트는 보통 래퍼 오브젝트라고 불리며 명시적인 포워딩 멤버는 래퍼 함수라고 불립니다.

위임

포워딩은 종종 위임을 혼동합니다.정식적으로는 상호 보완적인 개념입니다.어느 경우든 2개의 오브젝트가 있으며 첫 번째(송신, 래퍼) 오브젝트는 예를 들어 메서드를 호출하기 위해 두 번째(수신, 래퍼) 오브젝트를 사용합니다.그들은 무엇이 다른가self는, 수신 오브젝트(수신 오브젝트상의 메서드의 평가 환경에서는)를 참조합니다.위임에서는 송신 오브젝트를 참조하고, 전송에서는 수신 오브젝트를 참조합니다.주의:self는, 다이나믹 디스패치의 일부로서 암묵적으로 사용되는 경우가 많습니다(메서드명이 참조하는 함수).

전송과 위임의 차이는 래퍼를 통해 호출되었을 때 래피 내의 셀프파라미터 바인딩입니다.위임을 사용하면 self 파라미터는 래퍼에 바인드되고 전달과 함께 래피에 바인드됩니다.포워딩은 자동 메시지 재발송의 한 형태입니다.위임은 '일반'[1] 상속과 같이 컴파일/링크 시가 아니라 실행 시 부모(슈퍼 클래스)의 바인딩을 사용하는 상속 형식입니다.

예를 들어, 다음과 같은 코드가 지정됩니다.

// 보낸 사람 무효 n() {   인쇄물('n1'); }  // 수신기 무효 m() {   인쇄물("m2,");   n(); }  무효 n() {   인쇄물('n2'); } 

위임에 의해 이것은 출력됩니다.n()는 원래의 (표준) 오브젝트의 컨텍스트에서 평가됩니다.전송에서는, 다음의 이유로 출력됩니다.n()는 수신 [1]객체의 컨텍스트에서 평가됩니다.

일상적인 사용에서 포워딩은 종종 "위임" 또는 위임의 한 형태로 간주되지만, 신중한 사용에서는 무엇을 통해 명확하게 구별됩니다.self를 참조합니다.위임은 상속과 유사하며 평가 컨텍스트를 변경하지 않고 동작 재사용(구체적으로는 코드 재사용)을 가능하게 합니다.단, 전송은 (원래) 송신 객체가 아닌 수신(멤버) 객체에만 의존하기 때문에 구성과 유사합니다.두 경우 모두 재사용은 동적입니다. 즉, 실행 시(사용이 위임 또는 전송되는 개체에 기반함)에 결정되며, 컴파일/링크 시(에서 상속되는 클래스에 기반함)에 결정됨을 의미합니다.상속과 마찬가지로 위임을 통해 송신 객체는 원래 동작을 변경할 수 있지만 취약한 기본 클래스와 유사한 문제가 발생할 수 있습니다.또한 포워딩은 보다 강력한 캡슐화를 제공하여 이러한 문제를 회피합니다.[1]상속보다 구성을 참조하십시오.

Java에서의 명시적 포워딩의 간단한 예:B에 콜을 전송하다foo그 방법a필드:

학급 B {     A a;     T 후우() { 돌아가다 a.후우(); } } 

실행할 때 주의해 주세요.a.foo(),그this오브젝트는a(의 서브타입A원래 오브젝트(의 인스턴스)가 아닙니다.B) 더 나아가,a의 예가 될 필요는 없다A: 서브타입 인스턴스일 수 있습니다.실제로.A클래스가 될 필요도 없습니다.인터페이스 또는 인터페이스일 수도 있습니다.

상속과 대조됩니다.foo슈퍼클래스로 정의됩니다.A(인터페이스가 아닌 클래스여야 함) 및 서브클래스의 인스턴스에서 호출되었을 때B에 정의된 코드를 사용합니다.A단,this오브젝트는 아직 의 인스턴스입니다.B:

학급 A {     T 후우() { /* ... */ }; }  학급 B 확장 A { } 

이 Python 예제에서는 class.B전송하다foo메서드와x그 안에 있는 물체에 대한 속성a필드: 이러한 사용b(의 예)B)는, 에서 사용하는 것과 같습니다.b.a(의 인스턴스A전송처)를 참조해 주세요.

학급 A:     방어하다 __init__(자신, x) -> 없음.:         자신.x = x      방어하다 후우(자신):         인쇄물(자신.x)  학급 B:     방어하다 __init__(자신, a) -> 없음.:         자신.a = a      방어하다 후우(자신):         자신.a.후우()      @parames(@parames)     방어하다 x(자신):         돌아가다 자신.a.x      @x.세터     방어하다 x(자신, x):         자신.a.x = x      @x.삭제하다     방어하다 x(자신):          자신.a.x  a = A(42) b = B(a) b.후우()  # '42'로 출력합니다. b.x  # 값 '42' b.x = 17   # b.a.x 값이 17이 되었습니다.  b.x  # B.a.x 를 삭제합니다. 

간단하죠.

Java 예에서는Printer 클래스에는print방법.이 인쇄 방법은 인쇄 자체를 수행하지 않고 클래스 객체에 전달합니다.RealPrinter바깥세상에서는 이 같은 일이Printer오브젝트가 인쇄를 하고 있지만RealPrinterobject는 실제로 작업을 수행하는 것입니다.

전송이란 단순히 의무를 다른 사람에게 전가하는 것입니다.다음으로 간단한 예를 제시하겠습니다.

학급 리얼프린터 { // "실행"     무효 인쇄물() {          시스템..나가..인쇄("헬로우 월드!");      } }  학급 프린터 { // "실행"     리얼프린터 p = 신규 리얼프린터(); // 수신기를 만듭니다.     무효 인쇄물() {         p.인쇄물(); // 수신기를 호출합니다.     } }   일반의 학급 주된 {     일반의 정적인 무효 주된(스트링[] 논쟁들) {         // 외부에서는 프린터가 실제로 인쇄하는 것처럼 보입니다.         프린터 프린터 = 신규 프린터();         프린터.인쇄물();     } } 

복잡한

보다 복잡한 케이스는, 인터페이스를 사용하는 것으로, 전송의 유연성과 인쇄를 용이하게 할 수 있는 데코레이터 패턴입니다.여기서 말하는 '유연성'이란C언급할 필요가 없다A또는B포워딩의 전환이 추상화됨에 따라C이 예에서는 class가C인터페이스를 실장하는 모든 클래스에 전송 할 수 있습니다.I.학급C에는 다른 포워더로 전환하는 메서드가 있습니다.를 포함하여implements각 클래스는 인터페이스에 메서드를 구현해야 하므로 구를 사용하면 유형의 안전성이 향상됩니다.주요 트레이드오프는 더 많은 코드입니다.

인터페이스 I {  무효 f();  무효 g(); }   학급 A 용구 I {  일반의 무효 f() { 시스템..나가..인쇄("A: f() 실행 중"); }  일반의 무효 g() { 시스템..나가..인쇄("A: g() 실행 중"); } }   학급 B 용구 I {  일반의 무효 f() { 시스템..나가..인쇄("B: f() 수행"); }  일반의 무효 g() { 시스템..나가..인쇄("B: g() 실행 중"); } }   // 실행 시 구현 개체 변경(컴파일 시 실행 완료) 학급 C 용구 I {  I i = 무효;  // 전송  일반의 C(I i){ 설정(i); }  일반의 무효 f() { i.f(); }  일반의 무효 g() { i.g(); }    // 일반 속성  일반의 무효 설정(I i) { 이것..i = i; } }   일반의 학급 주된 {  일반의 정적인 무효 주된(스트링[] 논쟁들) {   C c = 신규 C(신규 A());   c.f(); // 출력:A: f()의 실행   c.g(); // 출력:A: g()의 실행   c.설정(신규 B());   c.f(); // 출력: B: doing f()   c.g(); // 출력: B: doing g()  } } 

적용들

포워딩은 많은 설계 [2]패턴에서 사용됩니다.전송은 몇 가지 패턴으로 직접 사용됩니다.

  • 책임사슬 패턴
  • 데코레이터 패턴: 데코레이터 오브젝트는 자신의 멤버를 추가하고 다른 멤버를 데코레이터 오브젝트에 전달합니다.
  • 프록시 패턴: 프록시 개체는 멤버 사용을 실제 개체로 전달합니다.

전송은 다른 패턴으로 사용할 수 있지만 많은 경우 변경이 이루어집니다.예를 들어, 어떤 오브젝트에서의 메서드 호출에 의해 다른 오브젝트로 여러 개의 메서드가 호출됩니다.

레퍼런스

  1. ^ a b c Büchi, Martin; Weck, Wolfgang (2000). "Generic Wrappers" (PDF). ECOOP 2000 — Object-Oriented Programming. Lecture Notes in Computer Science. Vol. 1850. pp. 212–213. doi:10.1007/3-540-45102-1_10. ISBN 978-3-540-67660-7.
  2. ^ Gamma, Erich; Helm, Richard; Johnson, Ralph; Vlissides, John (1995). Design Patterns: Elements of Reusable Object-Oriented Software. Addison-Wesley. Bibcode:1995dper.book.....G. ISBN 978-0-201-63361-0.