메서드와 클래스 모두에 대해 확장 할 수있는 이중 디스패치를 구현하는 방법을 찾고 있습니다.C#에서 double dispatch 구현 function 및 object가 모두 작동하도록 확장 가능
은 지금까지 나는 기본적으로 세 가지 방법을 사용 :
- 좋은
switch
(새 클래스를 추가하기 어려운 새로운 기능을 쉽게 추가 할 수) - 방문자 패턴 (매우 유사과 전통적인 절차 적 접근 : 쉽게
- ) 나는 보라 해요
) 새로운 기능을 추가 (새로운 클래스를 쉽게 추가 할 하드 간단한 인터페이스 방식을 새로운 클래스를 추가, 하드 새로운 방문자를 추가 함수 나 기존 클래스를 수정하지 않고도 새 함수와 새 클래스를 모두 추가 할 수있는 방법을 제공합니다.
적어도 프로그램 시작 후 한 번 수표를 찍은 후에는 개체/기능의 특정 조합을 요청할 때 실패하지 않아야합니다. 여기
내가 지금까지 사용되는 방법은 다음과 같습니다전통적인 절차 적 접근 :
enum WidgetType {A,B,C,}
interface IWidget
{
WidgetType GetWidgetType();
}
class WidgetA
{
public WidgetType GetWidgetType() {return WidgetType.A;}
}
class WidgetB
{
public WidgetType GetWidgetType() {return WidgetType.B;}
}
class WidgetC
{
public WidgetType GetWidgetType() {return WidgetType.C;}
}
// new classes have to reuse existing "WidgetType"s
class WidgetC2
{
public WidgetType GetWidgetType() {return WidgetType.C;}
}
class Functions
{
void func1(IWidget widget)
{
switch (widget.GetWidgetType())
{
case WidgetType.A:
...
break;
case WidgetType.A:
...
break;
case WidgetType.A:
...
break;
default:
// hard to add new WidgetTypes (each function has to be augmented)
throw new NotImplementedException();
}
}
// other functions may be added easily
}
전통적인 객체 지향 접근 방식 (방문자-패턴) :
interface IWidgetVisitor
{
void visit(WidgetA widget);
void visit(WidgetB widget);
void visit(WidgetC widget);
// new widgets can be easily added here
// but all visitors have to be adjusted
}
interface IVisitedWidget
{
void accept(IWidgetVisitor widgetVisitor);
}
class WidgetA : IVisitedWidget
{
public void accept(IWidgetVisitor widgetVisitor){widgetVisitor.visit(this);}
public void doStuffWithWidgetA(){}
}
class WidgetB : IVisitedWidget
{
public void accept(IWidgetVisitor widgetVisitor){widgetVisitor.visit(this);}
public void doStuffWithWidgetB(){}
}
class WidgetC : IVisitedWidget
{
public void accept(IWidgetVisitor widgetVisitor){widgetVisitor.visit(this);}
public void doStuffWithWidgetB(){}
}
class SampleWidgetVisitor : IWidgetVisitor
{
public void visit(WidgetA widget){ widget.doStuffWithWidgetA(); }
public void visit(WidgetB widget){ widget.doStuffWithWidgetB(); }
public void visit(WidgetC widget){ widget.doStuffWithWidgetC(); }
}
간단한 인터페이스 방식 :
IWidget
{
void DoThis();
void DoThat();
// if we want to add
// void DoOtherStuff();
// we have to change each class
}
WidgetA : IWidget
{
public void DoThis(){ doThisForWidgetA();}
public void DoThat(){ doThatForWidgetA();}
}
WidgetB : IWidget
{
public void DoThis(){ doThisForWidgetB();}
public void DoThat(){ doThatForWidgetB();}
}
WidgetC : IWidget
{
public void DoThis(){ doThisForWidgetC();}
public void DoThat(){ doThatForWidgetC();}
}
그러나 어떻게 "칼"과 같은 새로운 유형의 CollisionGroup을 추가 할 수 있습니까? enum은 확장 할 수 없습니다. 라이브러리에 코드의 일부를 배치하고 싶습니다. (나중에 코드를 변경하는 것을 싫어합니다.) – Onur
대답의 마지막 줄을 확인하십시오 - 확장 가능한 enum을 만들 수 있습니다 (enum은 실제로 int 또는 다른 원시 값 유형이라는 것을 기억하십시오) – AlexFoxGill
가능한 모든 조합이 availble인지, 즉 가질 수 있는지 미리 확인하고 싶습니다. 디폴트의 「오퍼레이션 없음」조작, 또는 사용시에 예외를 Throw합니다. 어떻게 그걸 처리 하겠니? – Onur