2011-09-22 7 views
1

나는 이러한 클래스를 생성 : 파생 클래스 가상 메서드를 호출하는 방법?

public abstract class Node 
{ 
    public virtual NodeModel CreateModel() 
    { 
     throw new NotImplementedException(); 
    } 
} 

public class Folder : Node 
{ 
    public virtual FolderModel CreateModel() 
    { 
     // Implementation 
    } 
} 

public class Item : Node 
{ 
    public virtual ItemModel CreateModel() 
    { 
     // Implementation 
    } 
} 

그런 다음 내 프로그램에 난 단지 항목 및 폴더 객체를 포함하는 노드의 목록이있다. 목록에서 반복하고 CreateModel() 메서드를 호출하려고하면 항상 Node 클래스 메서드가 호출되므로 예외가 throw됩니다.

파생 된 유형에 따라 반환 유형이 다르므로 CreateModel()을 abstract로 변경할 수 없습니다. 다른 반환 유형을 사용할 수 있는지 궁금합니다. 나는 또한 generics를 피하고 싶다. 사실 Intellisense는 그 인스턴스를 가지고 놀 때 상위 클래스 방법을 보여줍니다. 상위 클래스에서 가상 구현을 제거하면 기본 클래스 구현이 표시됩니다. 이것이 실제로 가능하다고 생각한 곳입니다.

그렇다면 프로그램이 상위 클래스 메소드를 호출하도록하려면 어떻게해야합니까?


편집 :는 대답은 실제로 간단하고 바로 내 코앞이었다. 반환 형식은 기본 클래스 추상 CreateModel()에 정의 된 반환 형식에서 상속되므로 중요하지 않습니다. 방금 기본 클래스에서 메서드를 추상으로 표시 했으므로 잘 작동합니다. 나는 왜 나에게 꽤 명백한 것 같기 때문에 내가 왜 어떤 순간에 혼란스러워하는지 모르겠다.

나를 도와 주신 모든 분들께 감사드립니다.

+1

에 CreateModel를 오버라이드 (override) 할 필요가 이렇게하려면 (예. 노드) 또는 서브 클래스 중 하나/파생 클래스 (항목 또는 폴더). 질문이 조금 불투명하기 때문에 업데이트하십시오. –

+0

이 실수를 지적 해 주셔서 감사합니다. – Ucodia

+0

C#은 반환 유형에 따라 메서드 확인을 수행 할 수 없으므로 Jon Skeet이 제안한 제네릭을 사용하지 않는 한 객체를 반환해야합니다. public virtual object CreateModel() –

답변

1

C 번호는 함수 반환 유형에 covariance을 지원하지 않습니다.

어쨌든 CreateModel()의 반환 형식을 NodeModel 이외의 다른 것으로 지정해야합니다. FolderModel이 더 많은 메소드로 NodeModel을 확장 할 때.

Node 객체 목록을 반복하고 CreateModel()을 호출하는 것이 필요하지 않은 경우 FolderModel을 반환하더라도 NodeModel 반환 유형으로 Folder.CreateModel()을 선언하면됩니다.

public abstract class Node 
{ 
    public virtual NodeModel CreateModel() 
    { 
     throw new NotImplementedException(); 
    } 
} 

public class FolderModel : NodeModel 
{ 
    // blah 
} 

public class Folder : Node 
{ 
    public virtual NodeModel CreateModel() 
    { 
     var node = new FolderModel(); 
     blah; 
     return node; // FolderModel derives from NodeModel 
    } 
} 

public class ItemModel : NodeModel 
{ 
    // blah 
} 

public class Item : Node 
{ 
    public virtual NodeModel CreateModel() 
    { 
     var node = new ItemModel(); 
     blah; 
     return node; // ItemModel derives from NodeModel 
    } 
} 

public foo(Node node) 
{ 
    var model = node.CreateModel(); 
} 

model의 유형은 노드의 유형에 따라 다릅니다

+0

귀하의 답변에 내가 누락 된 것이 나타났습니다. FolderModel이 NodeModel로부터 상속 받기 때문에 반환 유형은 중요하지 않습니다. 방금 기본 클래스에서 추상으로 함수를 선언하고 예상대로 작동합니다. 너와 다른 사람들에게 많은 감사를드립니다 :) – Ucodia

2

기본 클래스가 적절한 형식 인수를 지정하는 파생 클래스와 함께 일반 형식이어야하는 것처럼 보입니다. 대신 항상 혼란을 가져가는 방법 숨어 -

public abstract class Node<T> where T : NodeModel 
{ 
    public abstract T CreateModel(); 
} 

public class Folder : Node<FolderModel> 
{ 
    public override FolderModel CreateModel() 
    { 
     // Implementation 
    } 
} 

public class Item : Node<ItemModel> 
{ 
    public override ItemModel CreateModel() 
    { 
     // Implementation 
    } 
} 

지금 당신은 하나의 방법은 적절하게 오버라이드 (override)합니다.

편집 : 당신은 제네릭하지 않고 다음을 참조 할 수있게하려면, 당신은 항상 같은 비 일반적인 인터페이스를 만들 수 있습니다

public interface INode 
{ 
    NodeModel CreateModel(); 
} 

public abstract class Node<T> : INode where T : NodeModel 
{ 
    public abstract T CreateModel(); 

    // Explicit interface implementation so we can implement INode.CreateModel 
    // with a different return type. Just delegate to the strongly-typed method. 
    NodeModel INode.CreateModel() 
    { 
     return CreateModle(); 
    } 
} 
+0

예 나는 어떤 이유로 제네릭을 피하고 싶다. 세부 사항을 잊어서 미안하다. 나는 대부분 시간을 사용하지만,이 특별한 경우에, 나의 수업은 많은 방법으로 많은 파생을 가져올 것이고 이것은 너무 많은 복잡성을 추가 할 것입니다. 하지만 여전히 다른 방법이 없다면 아마이 아이디어를 다시 얻을 것입니다. 감사. – Ucodia

+0

@Ucodia : 메소드 숨기기를 사용하는 것보다 복잡성이 적다는 사실을 강하게 의심합니다. 다른 제안으로 편집 할 것입니다 ... –

+0

예 이것이 올바른 방법이라는 것을 알고 있지만 노드 구현은 완전하지 않으며 여기에서 문제가 발견됩니다. 이제는 제네릭을 사용해야 하겠지만 좀 더 반응을 기다릴 것입니다. – Ucodia

0

다음은 클래스 상속은 제네릭 대신에 사용되는 버전입니다. 모델의 특정 부분을 조작하는 것은 어떻게 든 각 특정 모델의 내부를 알고있는 가상 노드 메소드의 일부가되어야합니다.

0
public abstract class Node 
{ 
    public virtual NodeModel CreateModel() 
    { 
     throw new NotImplementedException(); 
    } 
} 

public class Folder : Node 
{ 
    public virtual FolderModel CreateModel() 
    { 
     // Implementation 
    } 
} 

이것은 오버라이드가 아니지만 과부하입니다.

Node node=new Folder(); 
node.CreateModel();//Of Folder 

당신이 기본 클래스를 의미합니까, "상"으로 파생 (폴더) 클래스

관련 문제