我阅读了很多关于C#的内容,并进行了我的第一次实践练习,但是我仍然是一个初学者,在尝试理解现有的,但尚未完成的MVC概念程序的某个时刻有点迷失。
我理解接口是什么以及如何实现接口到类或其他接口以获取对其包含的成员,函数等的访问,但在现有代码中我发现了接口的另一种用法(在声明中)类):
private IViewControl m_viewControl = null; private IModelControl m_modelControl = null;
这个代码没有出现在实现这两个接口的类中,但是在没有实现这两个接口的类中呢!
所以我的问题是:
非常感谢!
弯
请原谅我的英语,我不是母语人士。
嗨,
非常感谢你的答案,甚至不能说哪个是最好的,因为所有答案似乎都有帮助!我想我已经开始明白这是什么了。
再次感谢!
答案 0 :(得分:3)
包含这些行的类
private IViewControl m_viewControl = null;
private IModelControl m_modelControl = null;
对实现这些接口的其他类有2个引用。所以要回答你的第一个问题,这不是接口的实现,而是接口的使用。
回答你的第二个问题:这正是我们使用接口的原因。使用这些接口的类不关心它们的实现。在开发过程中,您可以为其中一个编写一个虚拟实现,因为您现在不需要它,但您仍然可以运行并测试应用程序的其余部分。
另一个例子:让我们想要编写一个使用某些数据库的应用程序的图像。将所有数据库逻辑放在接口后面。在应用程序的第1版中,您可以使用SQL数据库。写入数据库的类是否知道它是SQL数据库?不,他们不需要。所以现在你继续前进并决定要使用不同的数据库系统。您只需更改界面背后的实现和完成。
希望这有帮助。
答案 1 :(得分:1)
这是两个变量(实际上是成员变量,它们被称为字段,因为它们是封闭类型的成员)。
它们可用于存储实现该接口的任何项目,因此您可以将实现IViewControl
的任何内容放入m_viewControl
,将实现IModelControl
的任何内容放入m_modelControl
。
答案 2 :(得分:0)
这意味着,您可以分配给变量的对象必须实现接口。 所以它必须是接口的类型。
答案 3 :(得分:0)
你看到的是composition。这意味着您的类有两个字段,这些字段是这些类型的实例,而不是它正在实现它们的接口。
让我们用汽车来比喻。 “Car”是一个非常通用的概念,所以让它成为界面。丰田某人拥有的是某个类的实例(例如:Corolla),后者又实现了Car接口。另一方面,车轮是汽车的领域。你的卡罗拉轮胎可能属于倍耐力级,它实现了轮胎接口。但你的车不是轮胎 - 它有轮胎。
接口是一种在没有任何实现的情况下创建类型但无法实例化的方法。然后,您可以使用其他类型实现该接口,为其提供逻辑 - 因此您可以使用该接口的多种变体,每种变体都以不同的方式执行。关键是你要确保接口的所有实现者都有一组已知的方法签名和属性 - 你可能不知道它们是如何实现的,但你可以确定它们在那里。
如果你看一下C#中有很多类实现相同接口的命名空间,你可能会更好地了解它们的行为方式。例如,System.Collections中的许多类都实现了(惊讶)ICollection接口。这样可以确保所有集合都具有Count属性和具有已知签名的CopyTo方法。
答案 4 :(得分:0)
这种类型的用法非常适合限制特定对象的使用,或编写可以在任意数量的类上工作的公共代码。我们假设我们有一个名为Car的类,它实现了一个名为IDriveable的接口:
public class Car : IDriveable
现在,在其他一些类中,我们可以轻松地实例化Car对象,如下所示:
Car myCar = new Car();
但是,如果Car类有几个我们不希望在其他部分访问的公共方法怎么办?或者我们想编写一个可以在任何实现IDriveable接口的类上工作的函数?我们可以创建一个IDriveable接口本身的实例化,然后为它分配一个Car,如下所示:
IDriveable myDriveable = new Car();
然后,如果以下代码在IDriveable接口上运行,那么实现IDriveable的任何类都可以正常工作,例如:
private void TurnLeft(IDriveable vehicle)
P.S。你的英语用法很棒!
答案 5 :(得分:0)
接口的重要之处在于,您对 的内容不感兴趣,但可以做什么。因此,在这种情况下,您只对分配给该局部变量的任何对象的IViewControl
元素感兴趣,因此它可以是任何实现IViewControl
的类,并且很可能该类可以执行许多其他操作事情也是如此,但出于这些目的,它是IViewControl
的事实就是我们所关心的。
一个例子可能是我们有一个对可以飞行的东西感兴趣的类,它不关心其他任何东西,因此我们使用IFlyingThing
方法创建一个名为IFlyingThing.Fly()
的接口。然后我们可以有Bird
,Plane
,Butterfly
以及实现IFlyingThing
的各种其他类型,我们可以将它传递给我们的类,它只会看到{{ 1}}并在传递的实际对象上调用可能为IFlyingThing
或IFlyingThing.Fly()
的{{1}}。它并不关心对象是什么,只关心它可以飞行。
Bird.Fly()
也可以实现Plane.Fly()
,也可以实现Bird
,但我们的课只对IFeatheredAnimal
界面感兴趣,所以它不需要或不需要知道关于这些。
这有助于我们避免将代码紧密地绑在一起,并使Inversion of Control和Mock Objects等技术成为可能。
随着您学习C#的进展,您将使用很多接口。
答案 6 :(得分:0)
假设你有一个你不开发的课程。你只是消费它。您知道它可以生成一些文件并将其作为文件流返回给您。你不知道它是如何生成的,你不需要。您只知道它会返回一个文件流,然后您可以将其用于自己的目的。为了实现它,您与该类的开发人员签订合同,该类应该为您提供一个方法,该方法应该返回一个文件流,并且该方法的名称应该是ReturnStream,例如。该合同称为接口。当类的开发人员可以改变它的文件生成逻辑时。但它仍然具有相同的名称ReturnStream,它仍然会返回一个文件流。因此,您无需更改代码中的任何内容。
至于你的代码,你有两个IViewControl和IModelControl对象。您不开发模型和视图。您只需使用其他开发人员的逻辑,他们使用接口实现编写类。您可以按照自己想要的方式在代码中使用它们。但是许多开发人员可以创建不同的类,这些类实现了IViewControl和IModelControl接口。您可以通过简单地更改实现接口的类实例来使用它们。
答案 7 :(得分:0)
听起来你没有正确掌握接口的使用方式。让我用一个简单的例子来启发你:
class Driver{
// A driver has two cars - they are cars, since they are
// of types (classes Bmw and Audi) that implement the interface ICar:
ICar firstCar = MethodThatReturnsInstanceOfBmw();
ICar secondtCar = MethodThatReturnsInstanceOfAudi();
public void DriveAllCars(){
// The interface ICar has a method "Start()", which both
// cars must therefor implement. The Driver class can call
// these methods, because it knows about them from the interface.
firstCar.Start();
secondCar.Start();
}
}
类Driver
仍然不需要实现 ICar - 只需知道关于它(有引用它),所以它知道它能做什么做那种类型的“事情”。然后,它可以告诉汽车Start()
,而不会给啮齿动物后部提供有关发动机实际工作情况的信息。
将它与现实世界进行比较:您不需要驾驶汽车,也不需要成为机械师 - 您只需要了解驾驶的基本知识,这些对于大多数汽车来说都很常见,引擎和其他东西可能差别很大。
抽象和关于通用功能的协议,是接口的目的。
答案 8 :(得分:0)
接口基本上用于在不同的类之间实现类似的功能。 仅当通过依赖注入需要时,接口也用于创建类的对象。
例如:
Interface IMyClass{}
Class MyClass1:IMyClass
{
}
和
IMyClass obj;
因此你可以在一个类(IMyClass
)中注册obj和实现Bootstrapper
的类,并通过构造函数或方法将obj注入所有类,而不需要初始化它。 / p>
因此接口防止对对象进行无意义的创建,从而防止内存泄漏,正如我上面提到的,它有助于以不同的方式在不同的类之间实现相同的功能。