2009-04-16 5 views
3

나를 위해 여러 클래스를 생성하는 라이브러리를 사용하고 있습니다.baseclass 객체에서 하위 클래스 메서드를 호출하려면 어떻게해야합니까?

이러한 클래스는 모두 공통 기본 클래스에서 상속되지만 기본 클래스는 모든 하위 클래스에 공통적 인 몇 가지 메서드를 정의하지 않습니다. 예를 들어

는 :

SubClassA : BaseClass{ 
    void Add(ItemA item) {...} 
    ItemA CreateNewItem() {...} 
} 

SubClassB: BaseClass{ 
    void Add(ItemB item) {...} 
    ItemB CreateNewItem() {...} 
} 

불행하게도, 기본 클래스 이러한 방법이 없습니다. 이것은 좋은 것 :

BaseClass{ 
    // these aren't actually here, I'm just showing what's missing: 
    abstract void Add(ItemBaseClass item); // not present! 
    abstract ItemBaseClass CreateNewItem(); // not present! 
} 

내 A + B 객체에 대한 공통 기본 클래스 및 항목 개체에 대한 공통 기본 클래스가 있기 때문에, 나는 다형성의 멋진 세계의 혜택을 기대했다.

일반적인 메서드는 실제로 기본 클래스에 없기 때문에 사실상 호출 할 수는 없습니다. 예를 들어,이 완벽 할 것 :

BaseClass Obj; 
Obj = GetWorkUnit(); // could be SubClassA or SubClassB 

ItemBaseClass Item = Obj.CreateNewItem(); // Compile Fail: CreateNewItem() isn't in the base class 

Item.DoSomething(); 

Obj.Add(Item); // Compile Fail: Add(...) isn't in the base class 

분명히 작동합니다하지만 내가 혜택을 부정하는 것이다 있던 유형을 알아야 할 것 캐스팅.

어떻게 이러한 메서드를 호출 할 수 있습니까? 나는 전화하려고하는 메서드를 구현하지 않는 개체를 얻는 것에 대해 걱정하지 않습니다.

CType(Obj, Object).Add(Item) // Note: I'm using C#--NOT VB 

의 againt, 나는 (I 규칙 밖으로 부분 클래스를 생각한다) 이러한 클래스를 통해 제어 할 수 없습니다 : 나는 인텔리을하지 않지만 컴파일러의 행복하고 그것을 작동합니다 - 사실은 VB에서 내가 원하는 것을 할 수 있습니다 .

+0

그럼 방법 자체에 문제가 있습니까? Option Strict가 설정된 경우에만 광산을 사용하십시오 –

+0

하위 클래스를 제어 할 수 있습니까? 그럴 경우 Lucero의 솔루션으로 이동하십시오. –

+1

@Michael Haren : C#에는 Option Strict가 전혀 없습니다. 내 솔루션은 당신이 클래스를 제어 할 수 없다면 작동합니다. 당신이 서브 클래스를 제어한다면 Lucero의 솔루션이 가장 좋습니다. –

답변

6

반사 또는 다른 더러운 트릭을 사용하지 않고 파생 클래스의 가상이 아닌 메소드를 호출 할 수 없습니다. 당신이 그것을하고 싶은 경우에, 쉽게 다음입니다 :

// obj is your object reference. 
obj.GetType().InvokeMember("MethodName", 
    System.Reflection.BindingFlags.InvokeMethod, null, obj, null /* args */) 
+1

더러운 트릭을 기꺼이 사용합니다! 비주얼 베이직이 행복하게 받아 들일 수 있다면 * 미친 * 할 수는 없지만 ... 괜찮아요, 그럴 수는 있겠지만,보고 싶습니다 ... –

+0

왜 반사가 더러운가? :) 꽤 평범한 nowdays와 u는 리플렉션 없이도 코드를 평등하게 수행 할 수 있습니다. – majkinetor

+1

다형성을 사용해야 할 때 더러운 트릭으로 간주됩니다. –

0
+0

가상으로 선언 하시겠습니까? 메소드는 기본 클래스에 없습니다. –

+0

기본 클래스 메소드는 서브 클래스 구현에서 "override"키워드와 함께 가상이어야합니다. 아래 내 대답을 참조하십시오. –

+0

@ Kevin : 메소드가 기본 클래스에 없습니다. 나는 당신의 대답에 대해 더 논평했다. –

3
내가 모르는 뭔가가,하지만 왜하고 그 방법과 인터페이스를 상속하지 될 수

?

인스턴스의 생성 프로세스를 제어하는 ​​경우 작성하지 않은 클래스에서 상속하고 인터페이스를 추가하여 원하는 것을 얻을 수 있습니다 (코드를 작성할 필요가 없으며 컴파일러는 기존의 비 가상 메소드에 대한 인터페이스).

+0

그는 수업을 제어 할 권한이 없습니다. –

+0

어쩌면 나는 더 구체적이어야한다 ...;) – Lucero

+0

오른쪽. 이것이 내가 시작한 수업이지만 수업을 통제하지 못하면 할 수 없습니다. –

0

Visual Studio 2008을 사용하는 경우 기본 클래스의 확장 메서드를 만들 수 있습니다. 그 확장 메소드 안에서, 당신은 캐스트를하고 서브 클래스의 메소드를 호출 할 것입니다. 이것은 VS 2008 년 다른 제안 반사 코드를 대출 withing에에서만큼 당신이 컴파일하고 같이뿐만 아니라 2.0 프레임 워크를 대상으로 프로젝트 작업을해야 다음 ...

public static class MyExtensions 
{ 
    public static ItemBaseClass CreateNewItem(this BaseClass item) 
    { 
     return item.GetType().InvokeMember("MethodName", System.Reflection.BindingFlags.InvokeMethod, null, obj, null /* args */); 
    } 
} 
+0

몇 가지 코드 샘플을 보여줄 수 있습니까? 나는 그것을 깨끗하게 할 수 있다고 생각하지 않는다. –

+0

좋은 생각인데 요점은 이런 큰 스위치 블록을 제거하는 것입니다. 그래도 고마워. –

+0

스위치 블록을 원하지 않으면 반사 경로를 사용하십시오. 성능이 문제가되는 경우 스위치 블록이 더 나은 경로 일 수 있습니다. 확장 방법을 사용하면 해당 스위치를 쉽게 호출 할 수있는 방법으로 분리 할 수 ​​있습니다. –

0

또 다른 가능성은 사용하는 것입니다 할 수있는 RealProxy (성능면에서별로 효율적이지 않음)와 같은 프록시 메커니즘 또는 동적으로 생성 된 DynamicMethod를 사용하여보다 효율적으로 사용할 수 있으므로 리플렉션 오버 헤드가 반사 유형만큼 유연하게 유지하면서 지원 유형마다 한 번만 지원됩니다. . 이 방법을 여러 번 호출해야하지만 MSIL 지식이 필요합니다.

-1

하위 클래스의 메서드 정의에서 "override"키워드를 잊어 버렸습니다. 무언가가 "추상적"이라고 선언 될 때는 정의 상 가상이므로 하위 클래스에서는 메서드 선언 앞에 "override"키워드를 넣어야합니다. 따라서 작동해야하는 것은 다음과 같습니다.

BaseClass{ 
    abstract void Add(ItemBaseClass item); // not present! 
    abstract ItemBaseClass CreateNewItem(); // not present! 
} 

SubClassA : BaseClass{ 
    override void Add(ItemA item) {...} 
    override ItemA CreateNewItem() {...} 
} 

SubClassB: BaseClass{ 
    override void Add(ItemB item) {...} 
    override ItemB CreateNewItem() {...} 
} 

이것은 사용 예제에서 원하는대로 정확하게 작동합니다.

+0

@ 케빈, 도움을 주셔서 감사하지만 내가 보여 주려고했던 것은 내가 그 코드를 만질 수 없다는 것입니다. 나는 그것을 통제하지 않습니다. // 현재의 라인은 코드 파일에 실제로 존재하지 않습니다 - 만약 그들이 있다면 황금이 될 것입니다. –

+0

아, 알겠습니다. 따라서 기본적으로 공통 인터페이스를 선언하지 않는 인터페이스에 대한 동작을 찾고 있습니다. 일반적인 방법을 사용하는 경우 인터페이스를 구현하지 않으면 다소 엉성한 디자인이됩니다. 너무 나빴어. –

0

문제 # 1 : 서브 클래스가 어떤 문제 # 2를 오버라이드 (override)되지 않습니다 귀하의 하위 클래스가 기본 클래스와는 다른 기능의 서명이

당신이 그들을 무시하는 경우 귀하의 서명이 올바른지 확인, 마크 가상이면서 추상이 아닙니다. 기본 클래스 가상 함수에 빈 몸체를 추가해야한다.

class ItemBase{} 

class ItemA : ItemBase{} 

class ItemB : ItemBase{} 

class BaseClass 
{ 
    public virtual void Add(ItemBase item){} 
    public virtual ItemBase CreateItem() { return null; } 
} 

class ClassA : BaseClass 
{ 
    public override void Add(ItemBase item) 
    { 
     //do whatever 
     throw new NotImplementedException(); 
    } 

    public ItemBase CreateItem() 
    { 
     //create an ItemBase and return 
     throw new NotImplementedException(); 
    } 
} 
+0

MStodd, 제안에 감사하지만 불행히도 나는 수업을 제어 할 수 없습니다. 또한 이러한 메서드 호출은 실제로 기본 클래스 인 추상 또는 콘크리트에는 없습니다. –

관련 문제