views:

83

answers:

4

I have three classes that will each return a slightly different result.

// 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
   }
}

This will not work since the King overriden method of Get is expecting the Result class and will not accept its children ResultA and ResultB.

Is there a better approach I can take?

A: 

You should be able to explicitly cast ResultA and ResultB as Result in the implementations of Get (I'm assuming that's what the "concrete implementations" are intended to be).

TreDubZedd
+4  A: 

The usual approach is to use generics.

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();
    }
}

Edit: fixed syntax.

Mark H
"you can't make abstract methods which override an interface definition". I agree that this may be redundant, but it compiles fine. However, the OP's code (and your version) has several compilation errors, including missing parens and a messed up class definition.
Matthew Flaschen
I ended up flipping this and using an abstract class instead of an interface, since I wanted common properties of all the "King" classes. The key concept of using generics was what I was looking for though. Thanks!
Kenoyer130
+1  A: 

It will help if you use code that compiles. Your 'concrete implementations' are bogus, it looks like you mixed the concepts of class and method. There is otherwise no design problem here. For example:

public class KingA : King {
    public override Result Get() {
        return new ResultA();
    }
}
Hans Passant
+1  A: 

I think there's some syntax confusion here -- if I captured your intent correctly, this works fine:

// 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!");
        }
    }
}

(edited for formatting)

twon33