Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Interfaces and Headers

Today I ran across the concept of a C# Interface, I have one hopefully simple question to see if I understand them... Are they fairly similar to a C++ header file? I mean, from what I'm getting, you define the backbone of a class without actually defining what it does, that's kind of similar to a header, correct? I read the entire MSDN definition and it doesn't really make it 100% clear to me. I believe I have the idea (wrote and attached a very elementary program to see if I understood) but it's pretty important that I at least fully understand the basics of them by tomorrow evening.

Example:

namespace InterfaceTest
{
    class Program
    {
        static void Main(string[] args)
        {
            KitchenStaff newKitchen = new KitchenStaff();
            newKitchen.getBakers();
            newKitchen.getBaristas();
            newKitchen.getCooks();
            Console.ReadLine();

            KitchenDuties newKitchen1 = new KitchenDuties();
            newKitchen1.getBakers();
            newKitchen1.getBaristas();
            newKitchen1.getCooks();
            Console.ReadLine();
        }
    }

    interface Bakers
    {
        void getBakers();
    }
    interface Cooks
    {
        void getCooks();
    }
    interface Baristas
    {
        void getBaristas();
    }

    class KitchenInfo
    {
        private string m_kitchen_name = "";
        private Int16 m_bakers = 0;
        private Int16 m_baristas = 0;
        private Int16 m_cooks = 0;

        public string Name
        {
            get
            {
                return m_kitchen_name.ToString();
            }
            set
            {
                m_kitchen_name = value;
            }
        }
        public string Bakers
        {
            get
            {
                return m_bakers.ToString();
            }
            set
            {
                m_bakers = Convert.ToInt16(value);
            }
        }
        public string Baristas
        {
            get
            {
                return m_baristas.ToString();
            }
            set
            {
                if (value != string.Empty)
                {
                    m_baristas = Convert.ToInt16(value);
                }
            }
        }
        public string Cooks
        {
            get
            {
                return m_cooks.ToString();
            }
            set
            {
                if (value != string.Empty)
                {
                    m_cooks = Convert.ToInt16(value);
                }
            }
        }
    }

    class KitchenStaff : KitchenInfo, Bakers, Cooks, Baristas
    {
        public KitchenStaff()
        {
            Console.WriteLine("What is this kitchens name?");
            Name = Console.ReadLine();

            Console.WriteLine("How many bakers?");
            Bakers = Console.ReadLine();

            Console.WriteLine("How many baristas?");
            Baristas = Console.ReadLine();

            Console.WriteLine("How many cooks?");
            Cooks = Console.ReadLine();
        }
        public void getBakers()
        {
            System.Console.WriteLine("In {0} there are {1} bakers.", Name, Bakers);
        }
        public void getBaristas()
        {
            System.Console.WriteLine("In {0} there are {1} baristas.", Name, Baristas);
        }
        public void getCooks()
        {
            System.Console.WriteLine("In {0} there are {1} cooks.", Name, Cooks);
        }
    }
    class KitchenDuties : KitchenInfo, Bakers, Cooks, Baristas
    {
        public KitchenDuties()
        {
            Console.WriteLine("What is this kitchens name?");
            Name = Console.ReadLine();

            Console.WriteLine("How many bakers?");
            Bakers = Console.ReadLine();

            Console.WriteLine("How many baristas?");
            Baristas = Console.ReadLine();

            Console.WriteLine("How many cooks?");
            Cooks = Console.ReadLine();
        }
        public void getBakers()
        {
            System.Console.WriteLine("In {0}, the {1} bakers make fattening cookies.", Name, Bakers);
        }
        public void getBaristas()
        {
            System.Console.WriteLine("In {0}, the {1} baristas serve hot coffee.", Name, Baristas);
        }
        public void getCooks()
        {
            System.Console.WriteLine("In {0}, the {1} cooks make tender steak.", Name, Cooks);
        }
    }
}
like image 640
Volearix Avatar asked Mar 27 '14 19:03

Volearix


2 Answers

Conceptually it doesn't seem like you're understanding interfaces.

While interface in C# has a specific meaning, more generally in any object-oriented language, including C++, you can talk about the 'public interface' of a class. This is essentially what another class can see: it can't see private members, and it can't see the content of methods, it can only see the signatures of its public members.

So for example if I have a class:

public class MyClass
{
    private int _myPrivateInt;
    public int MyPublicInt;

    private void DoSomethingPrivate(int input)
    {
        //Some code goes here
    }

    public void DoSomethingPublic(int input)
    {
        //Some more code goes here
    }
}

All that is 'visible' of that to a different class will be:

int MyPublicInt;
void DoSomethingPublic(int input);

This is for the sake of encapsulation- one class shouldn't care about the specific implementation details of another class. MyClass publicly declares just what other classes need to know how to interact with it, and keeps everything else to itself.

So that's the idea of what an interface actually is, and in C# an interface is pretty much a way to specify just that information without the public methods. To understand why, you need to understand a related concept, polymorphism. Consider these classes:

public class InMemoryCustomerDataStorage
{
    public void StoreCustomerInfo(CustomerInfo info)
    {
        //Actual implementation goes here
    }

    public CustomerInfo RetrieveCustomerInfo(int customerId)
    {
        //Actual implementation goes here
    }
}

public class DatabaseCustomerDataStorage
{
    public void StoreCustomerInfo(CustomerInfo info)
    {
        //Actual implementation goes here
    }

    public CustomerInfo RetrieveCustomerInfo(int customerId)
    {
        //Actual implementation goes here
    }
}

public class FileCustomerDataStorage
{
    public void StoreCustomerInfo(CustomerInfo info)
    {
        //Actual implementation goes here
    }

    public CustomerInfo RetrieveCustomerInfo(int customerId)
    {
        //Actual implementation goes here
    }
}

All three serve the same purpose, but in different ways. They all allow you to store customer information, and retrieve it by an id. They may also have additional private members I haven't written out, for example the File one might have a method which creates the file if it doesn't already exist, etc. They would all have actual implementations rather than those comments, of course, I'm not writing them out fully because it's just an example.

So how would an interface come in handy here? Well the point is that parts of your program may want to store and retrieve customer information, but not care how it's done. In fact, generally speaking, they shouldn't specify exactly how to store it unless they directly need to care. What if as the program grows, you need to change which type of storage is used? You'd have to find every place you'd written InMemoryCustomerDataStorage and replace it with DatabaseCustomerDataStorage. Or what if you want to use a database most of the time, but when you're testing your code, you want to use in memory storage so that it runs fast? You could even be writing a library that needs to do data storage but doesn't itself include data storage classes. The solution to this is to use an interface. You'd write:

public interface ICustomerDataStorage
{
    void StoreCustomerInfo(CustomerInfo info);
    CustomerInfo RetrieveCustomerInfo(int customerId);
}

Then inside a class that needed to do some customer data storage could be something like:

public class NewCustomerProcessor
{
    private ICustomerDataStorage _storage;

    public NewCustomerProcessor(ICustomerDataStorage storage)
    {
        _storage = storage;
    }

    public void Process(string name, string address, string email, int age)
    {
        CustomerInfo info = new CustomerInfo(name, address, email, age);
        if(Validate(info))
            _storage.StoreCustomerInfo(info);
    }

    private bool Validate(CustomerInfo info)
    {
         //Some validation logic
    }
}

Now this class is fully functional, and at no point does it have to worry about which concrete implementation of ICustomerDataStorage is used. It could be stored in memory, in a file, in a database, it doesn't care. The class that implements ICustomerDataStorage could be in an entirely different assembly and project, I could put my project on github, and whoever downloads it to use in their own project could write their own implementation of ICustomerDataStorage.

like image 70
Ben Aaronson Avatar answered Oct 05 '22 19:10

Ben Aaronson


No, it is not similar to a header file. C++ has header files and cpp files so that the declaration and definition can be split. C# combines those so you don't have a separate declaration.

C# Interface does not have a direct equivalent in C++. The closest thing would be an abstract virtual class in C++.

like image 42
crashmstr Avatar answered Oct 05 '22 21:10

crashmstr