接口和报头

本文关键字:报头 接口 | 更新日期: 2023-09-27 17:54:04

今天我遇到了c#接口的概念,我有一个希望简单的问题,看看我是否理解它们…它们是否与c++头文件相当相似?我的意思是,从我得到的,你定义一个类的主干而不定义它做什么,这有点类似于header,对吧?我阅读了整个MSDN的定义,但它并没有让我100%清楚。我相信我有的想法(写了一个非常基本的程序来看看我是否理解)但是很重要的是,我至少要在明天晚上之前完全理解它们的基本知识。

例子:

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

接口和报头

从概念上看,你似乎没有理解接口。

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

例如,如果我有一个类:

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

所有对其他类可见的内容将是:

int MyPublicInt;
void DoSomethingPublic(int input);

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

这就是接口的概念,在c#中,接口就是一种不使用公共方法而指定信息的方式。要理解其中的原因,您需要理解一个相关的概念,多态性。考虑这些类:

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可能有一个方法,如果文件不存在,它会创建文件,等等。它们都有实际的实现,而不是那些注释,当然,我不会把它们全部写出来,因为这只是一个例子。

那么接口在这里是如何派上用场的呢?关键是,程序的某些部分可能想要存储和检索客户信息,但不关心如何完成。事实上,一般来说,它们不应该指定如何存储它,除非它们直接需要关心。如果随着程序的增长,您需要更改所使用的存储类型,该怎么办?你必须找到每一个写了InMemoryCustomerDataStorage的地方并用DatabaseCustomerDataStorage代替它。或者,如果您想在大多数时间使用数据库,但在测试代码时,希望使用内存存储以使其快速运行,该怎么办?您甚至可以编写一个需要进行数据存储但本身不包含数据存储类的库。解决这个问题的方法是使用接口。你会写:

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

然后在需要做一些客户数据存储的类中可以像这样:

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

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

不,它与头文件不同。c++有头文件和cpp文件,因此声明和定义可以分开。c#将它们组合在一起,这样你就不需要单独声明了。

c# Interface在c++中没有直接的等价。最接近的是c++中的抽象虚类。

不,它们不像C/c++中的头文件。它是"现代"语言(如c#和Java)中使用的概念。它允许每个类继承一组特征。

这是一个纯抽象类,它不包含任何代码,除了你想要继承的方法声明。

最常见的例子是c#中的IEnumerable接口,允许你在新定义的类对象上使用foreach语句。