简体   繁体   中英

C# Specify that a derived field is derived from its original class

Let's say I have a the classes A , B , C and D with B:A and D:C .

A has a field with a C object that gets inherited to B and is used in different methods in A . I know want to specify that in B , it is not only a C object, but a D object, but still utilize the methods in A that operate on the C object.

public class A 
{
    public C Obj { get; set; }

    public void DoStuff()
    {
        // Do stuff with Obj (C)
    }
}


public class B : A 
{
    public D Obj { get; set; } // This should also be the C Obj in A

    public void DoMoreStuff()
    {
        // Do stuff with Obj (D)
    }
}

public class C 
{
    // ...
}

public class D : C
{
    // ...
}

Specifically I need this to implement Binary Trees. A Binary-Search-Tree (BST) has a root that is a BST-Node and provides different methods that utilize it. A Red-Black-Tree is also a BST but the root is a RBT-Node, that is also a BST-Node, but additionally has a color attribute.

You can do what you want with a generic base class. Try starting with this:

public abstract class A<T> where T : C
{
    public T Obj { get; set; }

    public void DoStuff()
    {
        Console.WriteLine(typeof(T).FullName);
        Console.WriteLine(this.Obj.GetType().FullName);
    }
}

Now you can define A and B easily:

public class A : A<C>
{
}

public class B : A<D>
{
    public void DoMoreStuff()
    {
        this.DoStuff();
        Console.WriteLine(this.Obj.GetType().FullName);
    }
}

If I run this code:

var a = new A() { Obj = new C() };
var b = new B() { Obj = new D() };

a.DoStuff();

Console.WriteLine("...");

b.DoMoreStuff();

I get:

C
C
...
D
D
D

It's quite easy using generics:

public class A<T> where T : C 
{
    public T Obj { get; set; }

    public void DoStuff()
    {
        // Do stuff with Obj (C)
    }
}


public class B<T> : A<T> where T : D // this condition is valid since D inherits C
{
    public T Obj { get; set; } 

    public void DoMoreStuff()
    {
        // Do stuff with Obj (D)
    }
}

public class C 
{
    // ...
}

public class D : C
{
    // ...
}

You can add in some generics to gain access to the properties you want. I feel like this is a homework exercise, so I'll just give you the basics. See comments in the code for more details

public abstract class BaseTree<TNode>
    where TNode : BaseNode // TNode must be at least (base class) a BaseNode
{
    // Can be a collection as well, depending on your needs
    public TNode Node { get; set; }

    public void DoStuff()
    {
        // Node is a BaseNode
    }
}

// Any node in this tree is a RedBlackNode
public class RedBlackTree : BaseTree<RedBlackNode>
{
    public void DoMoreStuff()
    {
        // Node is a RedBlackNode
    }
}

public abstract class BaseNode
{
}

public class RedBlackNode : BaseNode
{
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM