Search code examples
c#binary-treemultiple-inheritance

c# confused about base class inheritance


I am confused as to exactly how classes inherit methods from each other. I already understand inheritance from base classes, there is however, certain code from an example that I do not understand. It involves searching a Binary tree and I could not find any resources that better explain how the code is inherited.

My aim is to understand it so that I can use it to also searched a linkedlist.

If any one can refer me to any relevant literature that explains this particular area I would be grateful.

I have highlighted the code section that I dont really yet understand how it is inhertied. The specific section is posted first:

public Company Read(string bezeichnung)
{
    return stri.Search(new Company() { Bezeichnung = bezeichnung });
}

Entire program:

using System;
using System.IO;
using System.Text;
using System.Net;

namespace CompanySearch
{
    class Program
    {
        static void Main(string[] args)
        {
            StreamReader r = new StreamReader(@"C:\Users\chris\Desktop\algo\fuckit\unternehmen.csv", Encoding.Default);
            Companies stri2 = new Companies(r);
            while (true)
            {
                Console.Write("Unternehmensbezeichnung eingeben: ");
                string name = Console.ReadLine();
                if (string.IsNullOrEmpty(name))
                    break;
                //Company konk = stri2.Read(name);
                Company konk = new Company();
                konk = stri2.Read(name);
                if (konk == null)
                    Console.WriteLine("Unternehmen nicht gefunden!");
                else
                    Console.WriteLine(konk + "\n");
            }
        }
    }

    public class Companies
    {
        private BinaryTree<Company> stri = new BinaryTree<Company>();
        public Companies(StreamReader rp)
        {
            // Spaltenüberschriften auslesen
            //var tokens = rp.ReadLine().Split(new char[] { ';' });
            //if (tokens.Length != 3)
            //    throw new ArgumentException("More than 3 columns in company file");
            string line;
            while ((line = rp.ReadLine()) != null)
            {
                var tokens = line.Split(new char[]{';'});
                //tokens = line.Split(new char[] { ';' });
                stri.Add(new Company()
                {Bezeichnung = tokens[0], Branche = tokens[1], Ort = tokens[2]});
            }

            rp.Close();
        }

        public Company Read(string bezeichnung)
        {
            return stri.Search(new Company()
            {Bezeichnung = bezeichnung});
        }
    }

    public class Company : IComparable<Company>
    {
        public string Bezeichnung
        {
            get;
            set;
        }

        public string Branche
        {
            get;
            set;
        }

        public string Ort
        {
            get;
            set;
        }

        public int CompareTo(Company other)
        {
            return Bezeichnung.CompareTo(other.Bezeichnung);
        }

        public override string ToString()
        {
            return string.Format("Bezeichnung: {0}\tBranche: {1}\tOrt: {2}", Bezeichnung, Branche, Ort);
        }
    }

    public enum TraverseModeEnum
    {
        PreOrder,
        PostOrder,
        InOrder,
        ReverseInOrder
    }

    public class BinaryTree<T>
        where T : IComparable<T>
    {
        private sealed class Node<TNode>
            where TNode : IComparable<TNode> // TNode muss IComparable implementieren
        {
            public TNode Item
            {
                get;
                set;
            }

            public Node<TNode> Left
            {
                get;
                set;
            }

            public Node<TNode> Right
            {
                get;
                set;
            }

            public int CompareTo(TNode other)
            {
                return Item.CompareTo(other);
            }
        }

        private Node<T> root;
        public int Count
        {
            get;
            private set;
        }

        public TraverseModeEnum TraverseMode
        {
            get;
            set;
        }

        public BinaryTree()
        {
            TraverseMode = TraverseModeEnum.PreOrder;
        }

        public void Add(T item)
        {
            if (root == null)
                root = new Node<T>()
                {Item = item};
            else
                addTo(root, item);
            Count++;
        }

        public void AddRange(T[] items)
        {
            foreach (var item in items)
                Add(item);
        }

        private void addTo(Node<T> node, T item)
        {
            if (item.CompareTo(node.Item) < 0)
            {
                if (node.Left == null)
                    node.Left = new Node<T>()
                    {Item = item};
                else
                    addTo(node.Left, item);
            }
            else
            {
                if (node.Right == null)
                    node.Right = new Node<T>()
                    {Item = item};
                else
                    addTo(node.Right, item);
            }
        }

        public bool Contains(T item)
        {
            Node<T> node = root;
            while (node != null)
            {
                int c = node.Item.CompareTo(item);
                if (c == 0)
                    return true;
                if (c > 0)
                    node = node.Left;
                else
                    node = node.Right;
            }

            return false;
        }

        public T Search(T item)
        {
            Node<T> node = root;
            while (node != null)
            {
                int c = node.Item.CompareTo(item);
                if (c == 0)
                    return node.Item;
                if (c > 0)
                    node = node.Left;
                else
                    node = node.Right;
            }

            return default (T);
        }

        public void Clear()
        {
            root = null;
            Count = 0;
        }

        public override string ToString()
        {
            string s = "";
            int level = 0;
            traverse(root, level, ref s);
            return s;
        }

        private void traverse(Node<T> node, int level, ref string s)
        {
            if (node == null)
                return;
            bool reverse = TraverseMode == TraverseModeEnum.ReverseInOrder;
            if (TraverseMode == TraverseModeEnum.PreOrder)
                s += "".PadLeft(level, ' ') + node.Item.ToString() + "\n";
            traverse(reverse ? node.Right : node.Left, level + 2, ref s);
            if (TraverseMode == TraverseModeEnum.InOrder || TraverseMode == TraverseModeEnum.ReverseInOrder)
                s += "".PadLeft(level, ' ') + node.Item.ToString() + "\n";
            traverse(reverse ? node.Left : node.Right, level + 2, ref s);
            if (TraverseMode == TraverseModeEnum.PostOrder)
                s += "".PadLeft(level, ' ') + node.Item.ToString() + "\n";
        }
    }
}

Solution

  • The class BinaryTree<T> down in the code demands that T must implement IComparable<T>. Lots of list-ish classes make similar demands. If a type implements IComparable<T> it means two instances of a class can be compared to each other with the ComparetTo( T t1, T t2 ) method. This method returns an indication of which T is greater than, less than, or equal to the other. Realize that the greater than, less than, or equal to is entirely up to the type that implements the interface. It's principally used for sorting or otherwise locating things in a tree, list, or other structure based on the comparison.

    Implementing an interface looks like class inheritance. The syntax is the same...but it's more like a contract, since an interface has no code to inherit. If you make a class that goes like:

    class MyClass: IComparable<MyClass>
    {
      //--> stuff
    }
    

    ...then you're obligated to have a publicly visible method with the signature:

    int CompareTo( MyClass a, MyClass b )
    {
       //--> look at the two instances and make a determination...
    }
    

    The method can use any characteristics of the class to determine what makes a greater than, less than, or equal to b...and thereby control how it's going to be placed into a structure.

    A class can inherit from only one other class...but it can implement as many interfaces as it needs. This is what, I'm guessing, looks like multiple inheritance.