0

I have a problem with abstract class and generic in c# (I usually code in Java) : here is the code I would like to use :

public interface InterfaceResult {...}

public abstract class Result : InterfaceResult {...}   
public class ResultA : Result {...}
public class ResultB : Result {...}

public interface InterfaceKing { InterfaceResult function();}

public abstract class King : InterfaceKing {
  public abstract Result function();
}
public class KingA : King {
  public override ResultA function(){...}
}
public class KingB : King {
  public override ResultB function(){...}
}

but that doesn t work : Visual Studio want for KingA and KingB to return an instance of Result with function(). If i use "new" instead of override, VS say I don t implement the required method (i need to use override).

So I tried with generic and it s not better

public abstract class Result    {    }
public class ResultA : Result    {    }
public class ResultB : Result    {    }

public interface IKing<T>    {T function();    }

public abstract class King<Result> : IKing<Result>
{
    public abstract Result function();

    public static implicit operator King<Result>(KingB v)
    {
        return v; // generate StackOverflow Exception
    }

    public static implicit operator King<Result>(KingA v)
    {
        throw new NotImplementedException();
    }
}

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

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

public class Test
{
    King<Result> a = new KingA(); // allowed by  public static implicit operator King<Result>(KingA v)
    King<Result> b = new KingB(); // allowed by  public static implicit operator King<Result>(KingB v)
    KingA ka = new KingA();
    List<King<Result>> lista = new List<King<Result>>();
    public void test()
    {
        lista.Add(ka);
    }        
}

How can i make this work ? I can t find any solution nor any good or complete example.

10
  • When you say trying with a generic is "not better", can you give a bit more detail there please? Commented Aug 4, 2016 at 8:51
  • You can't override an abstract method using a method that has a different signature. As for returing subclasses instead of a parent class in the definition, that's called covariance, it is allowed in generic interfaces but you have to specify the type as out T instead of just T, eg public interface IKing<out T> {T function(); } Commented Aug 4, 2016 at 8:52
  • Not sure to see what good using generics here can do ? (and almost the same for the interface) Commented Aug 4, 2016 at 8:59
  • With generic, i tried to do something like inheritance/polymorphism. Like in the second code. It does not work. I dont know what to return with the public static implicit operator. I cannot cast KingA in King<ResultA>. I also used in my real code out T. Does not work either. Commented Aug 4, 2016 at 9:03
  • inheritance/polymorphism are not related to generics Commented Aug 4, 2016 at 9:05

2 Answers 2

1

Moving from "full interface" to "no interface" (for lack of better terms) all that work (this Main works fine)

static void Main ()
{
    King a = new KingA ();
    King b = new KingB ();
    KingA ka = new KingA ();
    List<King> list = new List<King> ();

    list.Add (a);
    list.Add (b);
    list.Add (ka);
}

"full interface"

    public interface InterfaceResult { }

    public abstract class Result : InterfaceResult { }
    public class ResultA : Result { }
    public class ResultB : Result { }

    public interface InterfaceKing { InterfaceResult Function (); }

    public abstract class King : InterfaceKing
    {
        public abstract InterfaceResult Function ();
    }
    public class KingA : King
    {
        public override InterfaceResult Function () => new ResultA ();
    }
    public class KingB : King
    {
        public override InterfaceResult Function () => new ResultA ();
    }

"mixed (less interface)"

    public abstract class Result { }
    public class ResultA : Result { }
    public class ResultB : Result { }

    public interface IKing { Result Function (); }

    public abstract class King : IKing
    {
        public abstract Result Function ();
    }

    public class KingA : King
    {
        public override Result Function () => new ResultA ();
    }

    public class KingB : King
    {
        public override Result Function () => new ResultB ();
        {
            return new ResultB ();
        }
    }

"no interface"

    public abstract class Result { }
    public class ResultA : Result { }
    public class ResultB : Result { }

    public abstract class King
    {
        public abstract Result Function ();
    }

    public class KingA : King
    {
        public override Result Function () => new ResultA ();
    }

    public class KingB : King
    {
        public override Result Function () => new ResultB ();
    }
Sign up to request clarification or add additional context in comments.

4 Comments

ok I thought i could return a subtype without problem. I ll try to cast subtype to the returned object. Thank you for your answer. I can cast the returned object to the subtype.
if you need to subtype after that it probably means you have a design problem. All kings expect a Result as result (pun intended). So all Result should behave the same (after all they all are Result) the concrete implementation can vary between say a ResultA or a ResultB but the behaviour of all Result should be consistent
I want to generalize but in some particular case, i need to be sure to have a particular subtype. That s why i cast. Am i wrong?
wrong ; not necessarily ; there are scenarios where we don't have choice ; but most of the time it's a flawed design which is in cause. The polymorphism principle state "I want that behaviour (method) done regardless of which concrete type you really are" having to rely on which concrete type it is, it's tossing away all polymorphism benefit
0

Using covariance

See .net fiddler here. Read more about Covariance and Contravariance

public abstract class Result { }

public class ResultA : Result { }

public class ResultB : Result { }

public interface IKing<out T> where T : Result {}

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

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

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

public class TestClass
{
    King<ResultA> a = new KingA(); // allowed by  public static implicit operator King<Result>(KingA v)
    King<ResultB> b = new KingB(); // allowed by  public static implicit operator King<Result>(KingB v)
    KingA ka = new KingA();
    List<IKing<Result>> lista = new List<IKing<Result>>();

    public void Test()
    {
        lista.Add(ka);
    }        
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.