【问题标题】:what is the need to create instances of Interfaces?创建接口实例需要什么?
【发布时间】:2014-04-08 13:25:29
【问题描述】:

我正在研究接口并且已经知道我们无法创建接口的实例。我已经经历了一些已经在 stackoverflow 上提出的问题,但我更希望对所有人来说更基本的东西我的心态说。

所以我已经完成了这个示例,它在隐式实现接口并使用方法时工作得非常好,就好像方法是类本身一样。

namespace MyConsoleProject
{
    class Program : Iinterface
    {
        public int myfunc(int a, int b)
        {
            return a * b;
        }
        static void Main(string[] args)
        {
            Program obj = new Program();
            int result = obj.myfunc(10, 20);
            Console.WriteLine(result);
            Console.ReadLine();

        }
    }

    interface Iinterface
    {
        int myfunc(int a, int b);
    }
}

我对此没问题,但请看我调用接口的方式。我创建了一个实例 类并调用接口的函数。首先,我不清楚我调用的是接口方法还是类方法。由于类具有相同的方法和主体。那我为什么需要接口呢。

我经历过的最重要的一个是: 我什么时候需要创建这样的接口实例?

Iinterface objinterface=new Program ();

【问题讨论】:

  • 这会对你有所帮助 - stackoverflow.com/questions/16832280/…
  • 这就是我们所说的抽象。调用者不需要知道所有可用的派生类。假设我有 IPerson 由 Employee 、 User 和 Guest 继承。调用者可能不需要这些类。他可以通过接口访问所有这些。因此,每当引入新类时,调用者不会有太大变化。我们称它为 Facade。
  • 我已经为你编辑了标签;删除了不相关的标签并添加了相关的。

标签: c# .net


【解决方案1】:

我们不创建接口实例。您仍在此处创建类的实例。接口仅提供方法和属性的声明。但是,在实现时提供定义是类的责任。

现在我们什么时候使用接口?阅读有关松散耦合和后期绑定的信息。这是一个简单的例子来演示我们可以使用接口的情况。

/// <summary>
/// This class should have a method that returns price of pet food. This class should be able to handle different pet animals
/// which as of now, is unknown
/// </summary>
class PetFood
{
    public decimal GetFoodPrice(string petType)
    {
        IPetAnimal petAnimal = null;

        if (petType == "Dog")
        {
            petAnimal = new Dog();
        }
        else if (petType == "Cat")
        {
            petAnimal = new Cat();
        }
        else
        {
            MessageBox.Show("This animal is not supported yet.");
            return 0M;
        }

        return petAnimal.GetFoodPrice();
    }
}

interface IPetAnimal
{
    decimal GetFoodPrice();
}

class Dog : IPetAnimal
{

    public decimal GetFoodPrice()
    {
        return 10M;
    }
}

class Cat : IPetAnimal
{
    public decimal GetFoodPrice()
    {
        return 5M;
    }
}

【讨论】:

    【解决方案2】:

    请注意,您不能创建接口的实例。只有一个实现它的对象。

    如果您创建这样的对象,objinterface 将永远只有接口公开的属性和方法。除非你施放,否则你不能使用其余的。

    我发现这有两种方法:

    1) 您使用该接口来定义您希望对象履行的某种合同

    2) 您想限制对象的外部使用,因此将其用作这样的参数。这也允许传入任何实现接口的对象:

    public void MyMethod(Iinterface obj)
    

    或者当像这样传递一个 obj 时

    public Iinterface MyMethod()
    

    这样你可以限制使用你传递的东西(有点)。

    【讨论】:

      【解决方案3】:

      我举一个真实词的例子来解释界面的意思:界面就像我们对现实的形象,但每个人都有自己对现实的形象,所有的形象都是真实的! 这个现实有很多维度,但每个人都意识到其中的一些维度。

      【讨论】:

        【解决方案4】:

        假设你有这些类和一个接口:

        public interface IDoesSound {
          void Sound();
        }
        
        public class Dog : IDoesSound {
          public void Sound() {
            Console.WriteLine("Dog goes Woof!");
          }
        }
        
        public class Cat : IDoesSound {
          public void Sound() {
            Console.WriteLine("Cat goes Mew!");
          }
        }
        

        还有这个Main()

        static void Main(string[] args) {
          IDoesSound animal = new Cat(); // animal is an instance of Cat
          animal.Sound(); // output: Cat goes Mew!
        }
        

        IDoesSound animal 向编译器保证分配给animal 的对象将具有在IDoesSound 中声明的所有方法和属性,在本例中为void Sound()。因此,没有什么能阻止我们拥有IDoesSound animal = new Dog()

        另外,在Main() 中,每当我调用animal.Sound() 时,我不是 调用IDoesSound.Sound(),而是Cat.Sound()。接口所做的只是保证它具有IDoesSound 中的方法和属性。另一种说法是,通过拥有class Dog : IDoesSoundDog 承诺履行IDoesSound 指定的合同

        在一个更实际的示例中,假设您想要对一组数字进行平均。您将代码放在方法Average() 中。考虑一下这个 - 将哪个参数作为获取这些数字的参数会更好,Average(List&lt;double&gt;)Average(ICollection&lt;double&gt;)?让我们看看两者的合理实现。

        public static double Average(List<double> numbers) {
          var workingSum = 0.0;
          foreach (var num in numbers) {
            workingSum += num; 
          }
          return workingSum / numbers.Count; 
        }
        
        public static double Average(IEnumerable<double> numbers) {
          int count = 0;
          var workingSum = 0.0;
          foreach (var num in numbers) {
            count++;
            workingSum += num; 
          }
          return workingSum / count;
        }
        

        使用Average(List&lt;double&gt;),我别无选择以List&lt;double&gt; 或导数作为参数来调用它。我可以从其他集合中收集双精度,并使用或编写代码来转换它们,没错,但是使用Average(IEnumerable&lt;double&gt;),我确实不必担心它,只要参数实现IEnumerable&lt;T&gt;

        因此,接口是 LINQ 工作的重要组成部分,整个示例可以深入到(除了 .NET 框架之外什么都没有):

        IEnumerable<double> doubles = // get doubles from somewhere
        var average = doubles.Average();
        

        【讨论】:

          【解决方案5】:

          您不能创建接口的实例。接口是某种强制你实现其成员(没有实现代码)的契约

          【讨论】:

            【解决方案6】:

            您的代码将在您的类实例上调用myfunc() 方法。通过实现接口,您可以确保在接口中声明的方法在类中定义。

            【讨论】:

              【解决方案7】:

              -> 首先我不清楚我是调用接口方法还是类方法。

              您正在调用类方法。不能调用接口方法。其实接口没有方法,只是它的一个原型(即只有定义)。

              准确地说,你两个都没有打电话。您正在调用 Program 类的 obj 实例的方法。要像Program.myfunc(10, 20) 这样直接调用类的方法,您需要将方法设为静态。

              -> 那我为什么需要接口。

              你这里的代码很简单,所以你看不到界面的好处。类很少像你那样匹配它们的接口。类通常比接口具有更多的功能。所以接口类型定义了类必须具有的最小功能(即实现)。

              要使用简单的措辞(尽管不完全正确),您可以使用接口在多个类/对象之间定义一个通用(即共享)功能。这使得处理这些对象变得更加容易,而无需知道您正在处理哪个对象。

              例如,假设您正在创建一个包含多种武器的游戏。您可以创建具有SpeedStrength 成员以及Vibrate 方法的IWeapon 接口。您的每个武器类都将有更多的成员和方法,但它们都必须具有SpeedStrength 成员以及Vibrate 方法。因此,如果您有一些代码处理其中一个角色拥有的某些武器(即武器类的实例),并且您只需要访问这些武器的通用功能(由接口定义),您不需要需要知道你正在处理什么类型的武器。假设角色进入了一个带有重毒气体的房间,​​这会使所有武器的速度和力量降低 10% 并导致它们稍微振动,您可以像这样纠正一些代码:

              foreach(IWeapon w in myCharacter.Weapons) {
                w.Speed = w.Speed * 0.9;
                w.Strength = w.Strength * 0.9;
                w.Vibrate();
              }
              

              -> 我什么时候需要创建这样的接口实例?

              -> Iinterface objinterface=new Program ();

              当您只需要访问接口定义的通用功能并且不需要访问类定义的对象的额外功能时,这种代码很有用。当您构建对实现接口的类的所有对象进行操作的通用函数时,这尤其有用。例如,假设您要将上面的代码放在一个作为煤气室方法的函数中:

              public class GasRoom {
                public void ApplyGasEffect(IList<IWeapon> weapons) {
                  foreach(IWeapon w in weapons) {
                    w.Speed = w.Speed * 0.9;
                    w.Strength = w.Strength * 0.9;
                    w.Vibrate();
                  }
                }
              }
              

              注意参数类型IList&lt;IWeapon&gt;。现在你可以将我的角色拥有的所有武器的列表传递给这个函数,如下所示:

              myGasRoom.ApplyGasEffect(myCharacter.Weapons)
              

              假设你想在玩家开始舞台时首先给他们两把武器,然后玩家进入毒气室,现在你的代码行就派上用场了:

              //Give the player two weapons to start with.
              myCharacter.Weapons = new List<IWeapons>();
              IWeapon b = new Bazooka();
              myCharacter.Weapons.Add(w);
              IWeapon r = new Rocket();
              myCharacter.Weapons.Add(r);
              //Or you can do it all in one line like this:
              //myCharacter.Weapons = new List<IWeapons>() { new Bazooka(), new Rocket() };
              
              //////// Here goes some other code for the game //////
              //////// until the player enters the gas room ////////
              
              myGasRoom.ApplyGasEffect(myCharacter.Weapons)
              

              【讨论】:

                猜你喜欢
                • 2020-05-14
                • 2011-10-30
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2011-01-20
                • 2016-08-13
                • 2016-12-29
                相关资源
                最近更新 更多