zizou
zizou

Reputation: 49

C# : Override a property and return a derived type

Let's say I have a class A with the property "Details" that return an instance of class B.

public class A
{
    public virtual B Details {get; set;}
}

Lets say also, I have a class Aext (A extended) that inherits from A. But I want that Aext.Details return an instance of class Bext (B extended) :

public class Aext : A
{
    public override Bext Details {get; set;}
}

This will not compile because the type Bext must match the type inherited from A.
Of course, I can easily solve that by just put B as return of Details for Aext.

public class Aext
{
    B Details {get; set;}
}

Assignment will work, but I'll have to check everytime I use an instance of Aext if Details is Bext or B.

Do you see a way of doing something cleaner that this solution ?

Thank you.

Upvotes: 2

Views: 5458

Answers (3)

Vladimir Stokic
Vladimir Stokic

Reputation: 121

If you do not want to introduce interfaces, you can do something like this:

public class B
{ }

public class Bext : B
{ }

public class A
{
    public virtual B Details { get; set; }

    public A()
    {
        Details = new B();
    }

}

public class Aext : A
{
    public override B Details => new Bext();
}

However, I would suggest you go with composition and use dependency injection, like this:

public interface IB
{ }
public class B : IB
{ }

public class Bext : IB
{ }

public class A
{
    public virtual IB Details { get; set; }

    public A(IB details)
    {
        Details = details;
    }
}

public class TestClass
{
    public void TestMethod()
    {
        IB details = new B();
        IB extDetails = new Bext();

        A instance1 = new A(details);
        A instance2 = new A(extDetails);
    }
}

This way, you do not need to extend the inheritance hierarchy by creating Aext class. You can contain that strictly to the properties in question.

Upvotes: 0

Oleg Kulaev
Oleg Kulaev

Reputation: 46

Maybe you can try generics, something like this:

public class A<T> where T : B
{
    public T Details { get; set; }
}

public class Aext : A<Bext>
{
}

public class B
{

}

public class Bext : B
{

}

If you need you can override T Details with Bext Details, it will work fine.

Upvotes: 3

PhillipH
PhillipH

Reputation: 6222

No - but I think therefore it indicates the base class is flawed in its design. You are trying to force Interface behaviours onto an Abstract class/method. The base method does nothing, do what exactly is being inherited ? The base class could have a protected member of type B accessed by each inheritor and exposed via their own strongly typed accessor method. The value would be available to all inheritors, but consumers would need to get/set a strongly typed version of the data.

Upvotes: 0

Related Questions