接口和标头 [英] Interfaces and Headers

查看:121
本文介绍了接口和标头的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

今天我遇到了C#接口的概念,我有一个希望很简单的问题,看看我是否理解它们......它们是否与C ++头文件非常相似?我的意思是,从我得到的,你定义一个类的主干,而不是实际定义它的作用,这类似于一个标题,对吗?我阅读了整个MSDN定义,它并没有真正让我100%清楚。我相信我有这个想法(编写并附上了一个非常基本的程序,看看我是否理解)但是至少在明天晚上至少完全理解它们的基础知识非常重要。

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.

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);
        }
    }
}


推荐答案

从概念上讲,您似乎并不理解接口。

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

虽然C#中的接口具有特定含义,但更常见的是任何面向对象的语言,包括C ++在内,你可以谈论一个类的公共接口。这基本上是另一个类可以看到的:它看不到私有成员,也看不到方法的内容,它只能看到其公共成员的签名

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);

这是为了封装 - 一个类不应该关心另一个类的具体实现细节类。 MyClass公开声明其他类需要知道如何与它进行交互,并保留其他所有内容。

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.

这就是接口实际是什么的想法,以及在C#中,接口几乎是一种在没有公共方法的情况下仅指定信息的方法。要了解原因,您需要了解相关概念 polymorphism 。考虑这些类:

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
    }
}

所有三个都有相同的目的,但以不同的方式。它们都允许您存储客户信息,并通过ID检索它。他们可能还有其他我没有写过的私人成员,例如File one可能有一个创建文件的方法,如果它还不存在,等等。他们都会有实际的实现,而不是那些评论,当然,我不是完整地写出来的,因为它只是一个例子。

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.

那么界面怎么会在这里派上用场呢?重点是程序的某些部分可能想要存储和检索客户信息,但不关心它是如何完成的。实际上,一般来说,除非他们直接需要关注,否则他们不应明确指定如何存储它。如果程序增长,您需要更改使用哪种类型的存储?您必须找到您编写的每个地方 InMemoryCustomerDataStorage 并将其替换为 DatabaseCustomerDataStorage 。或者,如果您想在大多数时间使用数据库,但是在测试代码时,您希望在内存存储中使用它以便快速运行?您甚至可以编写一个需要进行数据存储的库,但本身并不包含数据存储类。解决方案是使用接口。你写的:

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
    }
}

现在这个类功能齐全,而且不必担心使用ICustomerDataStorage的具体实现。它可以存储在内存中,文件中,数据库中,它并不关心。实现ICustomerDataStorage的类可以在一个完全不同的程序集和项目中,我可以将我的项目放在github上,并且下载它以在自己的项目中使用的人可以编写自己的ICustomerDataStorage实现。

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.

这篇关于接口和标头的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆