简体   繁体   English

关于将 class 的实例分配给接口类型的问题

[英]Question about assigning a instance of a class to an interface type

I Don't understand some things about the below code, I wonder if you can help me.我不明白以下代码的一些内容,不知道您是否可以帮助我。

What first confused me is the following explanation from Microsoft docs;首先让我感到困惑的是微软文档中的以下解释;

在此处输入图像描述

What I didn't understand is why I am assigning "myClass" to variable "myInterface" of type "IMyInterface".我不明白为什么我将“myClass”分配给“IMyInterface”类型的变量“myInterface”。

Firstly, I'm surprised this is allowed, You can't assign a String to an Int variable, so why can i assign an instance of a class type to a variable of an Interface type?首先,我很惊讶这是允许的,您不能将字符串分配给 Int 变量,那么为什么我可以将 class 类型的实例分配给接口类型的变量?

Microsoft Docs mentions "an interface cannot be instantiated using the new operator", But why would you want to instantiate an interface. Microsoft Docs 提到“无法使用 new 运算符实例化接口”,但为什么要实例化接口。 Isn't the design of interfaces that they are just a contract enforcing any inheriting class to implement the properties and methods that the interface contains, why would you ever need to assign a class to an interface?接口的设计不就是它们只是强制执行任何继承 class 以实现接口包含的属性和方法的合同吗,为什么需要将 class 分配给接口?

I Investigated exactly the rules surrounding the Microsoft docs piece below, I realized that if you declare an interface, inherit it in another class, you can then assign the class that has inherited that interface to a variable of the interface type, then call the variable of the interface type as if it was a class ( the whydoesthiswork variable in the below code).我仔细研究了下面微软文档的规则,我意识到如果你声明一个接口,在另一个 class 中继承它,你可以将继承该接口的 class 分配给接口类型的变量,然后调用该变量接口类型,好像它是 class (以下代码中的Whydoesthiswork 变量)。

This hasn't helped me understand why this is possible, what the point in this confusing syntax is and why you would ever want to do this.这并没有帮助我理解为什么这是可能的,这种令人困惑的语法有什么意义,以及为什么你会想要这样做。

Any help would be appreciated, thank you.任何帮助将不胜感激,谢谢。

interface IAnimal
{
    void animalSound(); 
}

class Pig : IAnimal
{
    public void animalSound()
    {
        Console.WriteLine("The pig says: wee wee");   
    }
}

class Program
{
    static void Main(string[] args)
    {            
        IAnimal whydoesthiswork = new Pig();  
        whydoesthiswork.animalSound();
    }
}

You've discovered polymorphism - a core feature of object-oriented languages that allows you to treat objects as their parent class/interface.您发现了 多态性——面向对象语言的核心特性,它允许您将对象视为它们的父类/接口。

You can't assign a String to an Int variable, so why can i assign an instance of a class type to a variable of an Interface type?您不能将 String 分配给 Int 变量,那么为什么我可以将 class 类型的实例分配给 Interface 类型的变量?

A string and an int do not derive from each other - obviously assigning a string to an int doesn't make sense. stringint不是相互派生的 - 显然将字符串分配给 int 是没有意义的。 A pig is an animal, however, so it makes sense to treat it as such.然而,猪一种动物,因此这样对待它是有意义的。

why you would ever want to do this?为什么你会想要这样做?

It allows you to write code that works for any animal, such that if you introduce a new animal in the future, your code will stay the same.它允许您编写适用于任何动物的代码,这样如果您将来引入一种新动物,您的代码将保持不变。 Consider this function:考虑这个 function:

void Pet(Pig pig)
{
    Console.WriteLine("Petting...");
    pig.animalSound();
}

If tomorrow you decide to add a Dog class which can also be pet, you'd have to write an exact copy of this function, just replaced with Dog .如果明天您决定添加一个也可以是宠物的Dog class,那么您必须编写此 function 的精确副本,只需替换为Dog That's bad software design, Instead, we can write 1 generic function that works for both pigs and dogs!那是糟糕的软件设计,相反,我们可以编写 1 个通用的 function,它适用于猪和狗!

void Pet(IAnimal animal)
{
    Console.WriteLine("Petting animal...");
    animal.animalSound();
}

You don't have to do that in this limited example.在这个有限的示例中,您不必这样做。

If you have a lot of animal types though, you could pass them to functions that accept IAnimal rather than the concrete type.但是,如果您有很多动物类型,则可以将它们传递给接受IAnimal而不是具体类型的函数。 You could create a List<IAnimal> or IAnimal[] with different animals, iterate over them and call animal.animalSound() without knowing the concrete type.您可以使用不同的动物创建List<IAnimal>IAnimal[] ,在不知道具体类型的情况下对其进行迭代并调用animal.animalSound()

For example:例如:

interface IAnimal
{
    void makeSound(); 
    void Wake();
    void Sleep();
}

class Cat : IAnimal
{
...
}

class Dog : IAnimal
{
...
}

Assuming you have this method:假设你有这个方法:

void MoveAround(IAnimal animal)
{
    animal.Wake();
    animal.MakeSound();
    animal.Sleep();
}

You can apply it to an array of animals您可以将其应用于一系列动物

var animals=new[]{new Pig(), new Cat(), new Dog()};

foreach(var animal in animals)
{
    MoveAround(animal);
}

An interface is used to define a contract.接口用于定义合约。 It contains a set of members that types that implement the interface must implement.它包含一组实现接口的类型必须实现的成员。 So you can be sure that every type that implements the interface does at least support the members of the interface.因此,您可以确定实现该接口的每种类型至少都支持该接口的成员。

You can use an interface to declare a variable.您可以使用接口来声明变量。 Any instance that is assigned to it, must implement the interface.分配给它的任何实例都必须实现该接口。 If you use the variable, you can only use the members of the interface, not the ones of the actual instance.如果使用变量,则只能使用接口的成员,而不能使用实际实例的成员。

In your example, if you add another method to pig, you could not use this method because you declared the variable as the interface type:在您的示例中,如果您向 pig 添加另一个方法,则无法使用此方法,因为您将变量声明为接口类型:

interface IAnimal
{
    void animalSound(); 
}

class Pig : IAnimal
{
    public void animalSound()
    {
        Console.WriteLine("The pig says: wee wee");   
    }

   public void RollInTheDirt() 
   {
   }
}

class Program
{
    static void Main(string[] args)
    {            
        IAnimal whydoesthiswork = new Pig();  
        whydoesthiswork.animalSound();
        whydoesthiswork.rollInTheDirt(); // Error, because the variable is of type IAnimal, not of type Pig
    }
}

Why do you need this?你为什么需要这个?

You can use interfaces to define requirements towards type in a loosely coupled manner.您可以使用接口以松散耦合的方式定义对类型的要求。 If you have code that can run on all types of animals, because it only uses the AnimalSound method, you can use a parameter of type IAnimal instead of restricting the method to pigs by using Pig as the parameters type.如果您的代码可以在所有类型的动物上运行,因为它只使用AnimalSound方法,您可以使用IAnimal类型的参数,而不是通过使用Pig作为参数类型将方法限制为猪。 If you later decide to implement another kind of animal, let's say a bird, you can also implement the AnimalSound method with the sound of the bird.如果你以后决定实现另一种动物,比如说鸟,你也可以用鸟的声音来实现AnimalSound方法。 You can continue to use your method also with the bird - even though the animals do not have very much in common, but agreed to at least be able to make a sound.你可以继续用你的方法也与鸟——尽管动物没有太多共同点,但同意至少能发出声音。 This increases the flexibility of your code a lot.这大大增加了代码的灵活性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM