Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

How can I make 1 class (base, generic or something else) from these two classes?

class A
{
  A Link { get; set; }
}

class B
{
  B Link { get; set; }
}

UPD: This is what I have now:

class BSTree
{
  public BSTNode Root { get; set; }
}

class AVLTree
{
  public AVLNode Root { get; set; }
}

class BSTNode
{
  public BSTNode Parent { get; set; }
  public BSTNode Left { get; set; }
  public BSTNode Right{ get; set; }
  public int Key{ get; set; }
}

class AVLNode
{
  public AVLNode Parent { get; set; }
  public AVLNode Left { get; set; }
  public AVLNode Right{ get; set; }
  public int Key{ get; set; }
  public int Height { get; set;}
}

And finally I want to get something like BaseNode and BaseTree.

share|improve this question
add comment

2 Answers

up vote 8 down vote accepted

What is Link? If you have a base class Base with A : Base and B : Base, do you need to know that a.Link is of type A and b.Link is of type B?

If not, it is as easy as:

public abstract class Base
{
    public Base Link { get; set; }
}

If, on the other hand, you need to preserve the type of Link, then what about generics?

public class Common<T>
{
    public T Link { get; set; }
}

which can be used like this:

public static void Main()
{
    var number = new Common<int>
    {
        Link = 27,
    };

    var text = new Common<string>
    {
        Link = "Hello World",
    };

    // This is impossible, because of the mismatch between types.
    ////var wrong = new Common<float>
    ////{
    ////    Link = "I'm not a float.",
    ////};

    Console.WriteLine(number.Link);
    Console.WriteLine(text.Link);   
}

1. Refactoring: local method

Specifying both the generic type and the link is annoying, especially if you have to change the types a lot. In some cases, you may even mistakenly specify the wrong type: either a parent class or a class which supports implicit type conversion, resulting in difficult to find bugs.

To avoid this, you can create a method which initializes a new instance of the Common<T> class based on the link:

public static void Main()
{
    var number = CreateCommon(27);
    var text = CreateCommon("Hello World");

    Console.WriteLine(number.Link);
    Console.WriteLine(text.Link);
}

private static Common<T> CreateCommon<T>(T link)
{
    return new Common<T>
    {
        Link = link,
    };
}

public class Common<T>
{
    public T Link { get; set; }
}

2. Refactoring: factory pattern

The first refactoring is enough if you use the Common class in one method. If you're using it in several classes, then you'll end up duplicating code (i.e. copy-pasting the CreateCommon method), or refactoring the previous piece of code into a one which uses a factory:

public static void Main()
{
    var number = Common.Factory.Create(27);
    var text = Common.Factory.Create("Hello World");

    Console.WriteLine(number.Link);
    Console.WriteLine(text.Link);
}

public class Common<T> : Common
{
    public Common()
    {
        // Do something here.
    }

    public Common(T link)
        : this()
    {
        this.Link = link;
    }

    public T Link { get; set; }
}

public class Common
{
    public static CommonFactory Factory
    {
        get
        {
            return new CommonFactory();
        }
    }
}

public class CommonFactory
{
    public Common<T> Create<T>(T link)
    {
        return new Common<T>(link);
    }
}
share|improve this answer
    
Thanks for the answers! I updated my question. How can I use your answers for my situation? –  mif Jun 16 '13 at 22:57
    
@mif: BSTree and AVLTree can inherit from Tree<TNode> where TNode : Node; BSTNode and AVLNode — from Node. This way, you have a link between the types of trees and the corresponding types of nodes. –  MainMa Jun 17 '13 at 5:01
add comment
public abstract class Wrapper {
    private A theA;
    private B theB;
    // these are private on purpose.

    // add properties and methods for A and B stuff that you
    // want to expose. Make sure the names look like they're
    // all from one coherent class.
    // make them `protected` as needed for use by only the subclasses.

    // do not give a default constructor so you force subclasses
    // to build correctly
    public Wrapper (A a, B b) {
        // check for null!

        theA = a;
        theB = b;
    }
}
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.