接口和标头

Vol*_*rix 5 c# c++ inheritance interface

今天我遇到了C#接口的概念,我有一个希望很简单的问题,看看我是否理解它们......它们是否与C++头文件非常相似?我的意思是,从我得到的,你定义一个类的主干,而不是实际定义它的作用,这类似于标题,是正确的吗?我阅读了整个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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Ben*_*son 9

从概念上讲,您似乎并不了解界面.

虽然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
    }
}
Run Code Online (Sandbox Code Playgroud)

对于另一个班级而言,所有这些都是"可见的"将是:

int MyPublicInt;
void DoSomethingPublic(int input);
Run Code Online (Sandbox Code Playgroud)

这是为了封装 - 一个类不应该关心另一个类的具体实现细节.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
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

public interface ICustomerDataStorage
{
    void StoreCustomerInfo(CustomerInfo info);
    CustomerInfo RetrieveCustomerInfo(int customerId);
}
Run Code Online (Sandbox Code Playgroud)

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

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
    }
}
Run Code Online (Sandbox Code Playgroud)

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


cra*_*str 1

不,它与头文件不同。C++有头文件和cpp文件,这样声明和定义可以分开。C# 将这些结合起来,因此您无需单独声明。

C#Interface在 C++ 中没有直接等效项。最接近的东西是 C++ 中的抽象虚拟类。