2014-10-14 13 views
2

기존 코드 기반을 정리하려고하는데 추상 클래스의 여러 파생 클래스에 대한 일반 참조 이름을 사용하는 데 문제가 있습니다. 예를 들어추상 기본 클래스를 사용하여 C# 런타임 다형성

:

public abstract class Base<T> : Utilities.CommonRequiredObject 
{ 
    protected List<T> RawContents = new List<T>(); 
    . 
    . 

    public abstract void LoadContents(List<T> Contents);  // Each Class needs to load and process differently 
    protected List<T> Contents; 

    public virtual void DoSomething()   // Default here for common use. Defined in Each class for its specifics (if needed) 
    { 
    ... 
    } 
    public abstract List<T> FunctionToGetContents(); 

} 

public class FOO : Base<string> 
{ 
    public override void DoSomething() ... 
    public override List<string> FunctionToGetContents() ... 
} 

public class BAR : Base<byte> 
{ 
    public override void DoSomething() ... 
    public override List<byte> FunctionToGetContents() ... 
} 

홈페이지 로직은 공통 변수를 사용하려고합니다. 사용할 새 클래스를 만들고 싶지만 런타임 다형성 방식으로 사용하고 싶습니다. 다음 코드

IE: Base<T> ObjectToUse; 

이 방법은, 내가 단순히 ObjectToUse를 참조 할 수 있습니다 : 클래스는 일반적인 기능을 가지고 있고, 필요한 재정을 가지고, 나는 인스턴스를 생성하고 사용할 수 있도록하려면 일반적인 방법을 호출하십시오. 다른 기본 클래스에서 몇 가지 공통 루틴을 상속 받았기 때문에 인터페이스를 사용할 수 있는지 없는지 확실하지 않습니다.

if(variable) 
{ 
    FOO ObjectToUse = new FOO(); 
} 
else 
{ 
    BAR ObjectToUse = new BAR(); 
} 

ObjectToUse.LoadContents(ObjectToUse.FunctionToGetContents()); 
ObjectToUse.DoSomething(); 
... 

편집 : 내가 빨리 접수 된 의견을 바탕으로이 (덕분에 다시 모두)가) 일반 (Base<T>)를 제거하는 것보다 더 나은 입력 자료 (모든 수업을 것입니다, 나는이를 정의 할 수 있습니다 ObjectToUse 단순히 Base ObjectToUse;으로 생각합니다.

+1

이 작동하지 않을. 당신의 클래스'Base '와'Base '는 공통 조상을 가지고 있지 않습니다. – Sjips

+0

인터페이스를 사용하지 않는 이유는 무엇입니까? 'FOO'와'BAR' 둘 다'DoSomething()'메소드 서명을 선언 한'IDoSomething'을 구현했다면, 당신은 사업을 할 수 있습니다. – 48klocs

+0

@Sjips 사실 그들은 (CommonRequiredObject)하지만 그에게 쓸모가있는 것은 아닙니다. – BradleyDotNET

답변

4

이 작업을 수행 할 수 없습니다.

제네릭 형식 매개 변수가 필요한 참조를 사용하면이를 제공해야합니다. 여기에 dynamic을 활용하여 유형을 런타임에 평가할 수 있지만 얻을 수있는 최상의 결과를 얻을 수 있습니다.

템플릿 메서드 패턴과 같은 것을 사용하더라도 제네릭 형식 인수를 지정해야합니다. 이것을 위해 DoSomething 메소드를 원한다면 타입에 대한 참조를 보유 할 수 있도록 상위 기본 클래스 (또는 인터페이스)로 승격되어야하며 해당 (비 - 제네릭) 함수를 호출하십시오.

귀하의 의견에 내가 취할 해결책은 다음과 같습니다. 공통 코드를 기본 클래스 내의 템플릿 메소드 패턴 으로 리팩토링하십시오. 그런 다음 "트리거링"기능을 비 제너릭 기본 클래스 (또는 인터페이스)에서 일반 제네릭 상속 된 멤버로 만듭니다. 이제 해당 유형에 대한 참조를 보유 할 수 있으며 템플리트 메소드를 호출하여 다른 호출을 발생시킬 수 있습니다. 그런 다음

public void DoAwesomeStuff() //inherited from non-generic parent or interface 
{ 
    LoadContents(FunctionToGetContents()); 
    DoSomething(); 
} 

:

IDoesAwesomeStuff ObjectToUse = new FOO(); 
ObjectToUse.DoAwesomeStuff(); 
+0

확인.그래서 이것은 Base()의 부모로 옮겨 갈 것입니다. 아마도 Utilities.CommonRequiredObject는 많은 곳에서 공유되는 몇 가지 기본적인 기능을 가지고 있기 때문에 새로운 코드가 될 것입니다. Base : NewBase를 입력 한 다음 공통 함수를 NewBase()로 옮겼습니다. 그런 다음 NewBase ObjectToUse()를 호출하고 ObjectToUse.DoAwesomeStuff()를 호출합니다. –

+1

@StevenScott (자주 사용되는) 기본 클래스를 수정하지 않으려면이 클래스를 상속 할 수 있으므로 인터페이스에 추가하는 것이 좋습니다. 기본 기능을 수정하는 것도 효과가 있습니다. 분명히 "중간"기본 클래스도 작동하지만, 내가 필요하다고 생각하는 것은 아닙니다. – BradleyDotNET

+1

@StevenScott 인터페이스를 사용하지 않으려는 경우 편집 된 주석이 작동합니다. – BradleyDotNET

관련 문제