Как заставить абстрактный метод возвращать абстрактный тип с конкретными реализациями? - PullRequest
2 голосов
/ 15 сентября 2010

У меня есть три класса, каждый из которых будет возвращать немного разные результаты.

// interfact to a king
public interface IKing{
  public Result Get();
}

// main abstract class
public abstract class King:IKing{
  public abstract Result Get();
}

// main abstract result
public abstract class Result{
  public int Type {get;set;}
}

// KingA result
public class ResultA:Result{
   ...
}

// KingB result
public class ResultB:Result{
   ...
}

// concrete implementations
public class KingA:King{
   public override ResultA Get(){
     return new ResultA;
   }
}

public class KingB:King{
   public override ResultB Get(){
     return new ResultB
   }
}

Это не будет работать, поскольку переопределенный метод King для Get ожидает класс Result и не будет принимать его дочерние элементы ResultA и ResultB.

Есть ли лучший подход, который я могу выбрать?

Ответы [ 4 ]

4 голосов
/ 15 сентября 2010

Обычный подход - использовать дженерики.

public interface IKing<T> where T:Result{
    T Get();
}

public class King<T> : IKing<T>
   public abstract T Get();
}

public class KingA : King<ResultB> {
    public override ResultA Get(){
        return new ResultA();
    }
}

public class KingB : King<ResultB> {
    public override ResultB Get(){
        return new ResultB();
    }
}

Редактировать: фиксированный синтаксис.

1 голос
/ 15 сентября 2010

Я думаю, здесь есть некоторая путаница с синтаксисом - если я правильно уловил ваше намерение, это прекрасно работает:

// interface to a king
public interface IKing
{
    Result Get();
}

// main abstract class
public abstract class King : IKing
{
    public abstract Result Get();
}

// main abstract result
public abstract class Result
{
    private int _Type;
    public int Type { get { return _Type; } set { _Type = value; } }
}

// KingA result
public class ResultA : Result
{

}

// KingB result
public class ResultB : Result
{

}

// concrete implementations
public class KingA : King
{
    public override Result Get()
    {
        return new ResultA();
    }
}

public class KingB : King
{
    public override Result Get()
    {
        return new ResultB();
    }
}

class Program
{
    static void Main(string[] args)
    {
        IKing ka = new KingA();
        IKing kb = new KingB();

        Result ra = ka.Get();
        Result rb = kb.Get();

        if (ra is ResultA)
        {
            Console.WriteLine("A ok!");
        }

        if (rb is ResultB)
        {
            Console.WriteLine("B ok!");
        }
    }
}

(отредактировано для форматирования)

1 голос
/ 15 сентября 2010

Это поможет, если вы используете код, который компилируется. Ваши «конкретные реализации» являются поддельными, похоже, вы смешали понятия класса и метода. В противном случае здесь нет проблем с дизайном. Например:

public class KingA : King {
    public override Result Get() {
        return new ResultA();
    }
}
0 голосов
/ 15 сентября 2010

Вы должны иметь возможность явно приводить ResultA и ResultB как Result в реализациях Get (я предполагаю, что это именно то, для чего предназначены "конкретные реализации").

...