【问题标题】:Why is this interface implemented within the class this way?为什么这个接口在类中以这种方式实现?
【发布时间】:2017-03-08 01:02:41
【问题描述】:

我以前没有见过作为类成员实现的接口。有人可以解释发生了什么吗?你可以实例化一个接口吗?这些接口所需方法的实现在哪里?

public class MyClass
{
    private readonly ITest1 interface1;
    private readonly ITest2 interface2;
    private readonly ITest3 interface3;

    public MyClass(ITest1 interface1, ITest2 interface2, ITest3 interface3)
    {
        this.interface1 = interface1;
        this.interface2 = interface2;
        this.interface3 = interface3;
    }

    public void TestMethod()
    {
        var lines = interface1.GetData();
        var file = interface2.Parse(lines);
        interface3.Copy(file);
    }
}

与我平时使用接口的方式相比有什么不同:

public class Person : IEquatable<Dog>
{
    public int Age { get; set; }

    public bool Equals(Dog d)
    {
        if (d.Age == this.Age)
            return true;
        else
            return false;
    }
}

public class Dog
{
    public int Age { get; set; }
}

【问题讨论】:

  • 无意冒犯,但我认为您确实需要阅读一些有关 C# 的教程,特别是接口的工作原理。
  • 我找不到任何可以解释第一个示例的内容。我发现的只是与第二个示例类似的东西。
  • 他们没有实例化接口,他们使用实例(像往常一样)但响应给定接口 - 这意味着他们实现了其中定义的方法 - 但实现不在接口中
  • 我了解到您在接口之外实现了方法,就像我在第二个示例中所做的那样。我还是不明白第一次发生了什么。

标签: c# interface


【解决方案1】:

区别在于:

您对Person 类所做的是接口实现

MyClass 没有实现任何接口,但它接受接口作为构造函数参数。调用构造函数的人将提供实现接口的实例。更多内容如下。

你可以实例化一个接口吗?

没有。实现该接口的类将被实例化。

这些接口所需的方法的实现在哪里?

当这个人创建你的类的实例时,他们将传递一个实现接口的类的实例。像这样:

public interface ITest1
{
    string GetData();
}
public class Test1 : ITest1
{
    public string GetData()
    {
        return "Data";
    }
}

他们会这样称呼你的班级:

var test1 = new Test11();

// instead of nulls it will be other instances like test1
var myClass = new MyClass(test1, null, null);

我以前没有见过作为类成员实现的接口。有人可以解释发生了什么吗?

我上面已经用一个例子解释了发生了什么。

这实际上是一种非常常见的方式,是的,还有其他方式,但这是其中一种方式。

优势

  1. 这样您的MyClass 不知道将传递什么具体类型,但它知道具体类型是什么,它将支持接口。

  2. MyClass 中,您将只有依赖于接口的代码,因此您的类是松散耦合的。

  3. 依赖注入可用于将依赖注入MyClass 的构造函数。这称为构造函数注入。

与我平时使用接口的方式相比有什么不同:

没有区别。但是您需要考虑人们将如何使用该课程。例如,如果你想使用MyClass,你会这样做,这正是你所习惯的:

public class Test1 : ITest1
{
    public string GetData()
    {
        return "Data";
    }
}

为了进一步澄清,假设MyClass 有另一个这样的构造函数和字段:

private readonly IEquatable<Dog> iEq;
public MyClass(IEquatable<Dog> iEq) { this.iEq = iEq; }

然后你可以用你的 Person 类的实例来调用它。所以没有什么不同。

注意:没有人会因为被等同于狗而感到高兴;)

【讨论】:

  • 这是有道理的。基本上,接口只代表实现该契约的任何类。这就是我所困惑的。正如你所说,只要它实现了接口,你传入的具体类型并不重要。谢谢!
【解决方案2】:

你不能实例化一个接口;派生类将传递给构造函数。

所以你会有一些课程:

class A : ITest1 {  }
class B : ITest2 {  }
class C : ITest3 {  }

并像这样使用它们:

var a = new A();
var b = new B();
var c = new C();
var mc = new MyClass(a, b, c);
mc.TestMethod();

【讨论】:

    【解决方案3】:

    不能实例化接口,可以用他继承的类型替换接口!

    这是接口的常规用法(您的示例):

    public class MyClass
    {
        public MyClass(ITest1 interface1, ITest2 interface2, ITest3 interface3)
        {
            this.interface1 = interface1;
            this.interface2 = interface2;
            this.interface3 = interface3;
        }
    
        public void TestMethod()
        {
            var lines = interface1.GetData();
            var file = interface2.Parse(lines);
            interface3.Copy(file);
        }
    
        private readonly ITest1 interface1;
        private readonly ITest2 interface2;
        private readonly ITest3 interface3;
    }
    

    您在MyClass 类中创建了三个字段:interface1、interface2 和 interface3。

    通过类构造函数,您可以为ITest1ITest2ITest3 注入真实实例。这些实例应该是一些实现了相应接口的类。

    示例:

    您可以实现接口并提供如下示例中的对象:

    public class Test1 : ITest1 
    {
        public string GetData()
        { 
           // code
        }
    }
    
    public class Test2 : ITest2
    {
        public string GetData()
        { 
           // code
        }
    }
    
    public class Test3 : ITest3
    {
        public string GetData()
        { 
           // code
        }
    }
    

    创建MyClass 的示例如下:

    var test1 = new Test1();
    var test2 = new Test2();
    var test3 = new Test3();
    var myClass = new MyClass(test1, test2, test2);
    

    对象test1test2test3 实现接口ITest1ITest2ITest3

    结论

    没有魔法。 接口被其继承类型的类型替换!基本上,您正在为代码中的抽象提供实现。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-11-28
      • 1970-01-01
      • 2023-04-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多