我可以在接口中声明函数和属性,但我无法实现它们.当我从界面继承时,我现在必须在我的班级中实现所有这些成员.如果我必须这样做,那么声明界面有什么意义呢?
例如,这是一个示例界面:
namespace InterfaceExample
{
public interface IVehicle
{
int Doors { get; set; }
int Wheels { get; set; }
Color VehicleColor { get; set; }
int TopSpeed { get; set; }
int Cylinders { get; set; }
int CurrentSpeed { get; }
string DisplayTopSpeed();
void Accelerate(int step);
}
}
Run Code Online (Sandbox Code Playgroud)
我已在此界面中声明了所有属性和函数.现在,当我在我的班级中使用这个界面时:
namespace InterfaceExample
{
public class Motorcycle : IVehicle
{
private int _currentSpeed = 0;
public int Doors { get; set; }
public int Wheels { get; set; }
public Color VehicleColor { get; set; }
public int TopSpeed { get; set; }
public int HorsePower { get; set; }
public int Cylinders { get; set; }
public int CurrentSpeed
{
get { return _currentSpeed; }
}
public Motorcycle(int doors, int wheels, Color color, int topSpeed, int horsePower, int cylinders, int currentSpeed)
{
this.Doors = doors;
this.Wheels = wheels;
this.VehicleColor = color;
this.TopSpeed = topSpeed;
this.HorsePower = horsePower;
this.Cylinders = cylinders;
this._currentSpeed = currentSpeed;
}
public string DisplayTopSpeed()
{
return "Top speed is: " + this.TopSpeed;
}
public void Accelerate(int step)
{
this._currentSpeed += step;
}
}
Run Code Online (Sandbox Code Playgroud)
我必须再次声明所有属性.
那么为什么首先要使用界面呢?这似乎是浪费时间,因为无论如何我将实现我班上的所有成员.
至于其他的答案强调interfaces告诉你what to do,并how to do为你来实现.
1.那么为什么我浪费时间创建一个接口如果我必须在我的类中声明My Interface的所有属性和功能.
好.您正在创建Motorcycle和实现接口IVehicle的MotorCycle类is forced to implement all the members of the interface IVehicle.
如果你没有使用所谓的接口IVehicle,你实际上可能forget对implement something你应该已经实现.
明天,如果有人想构建一个Car可以实现的IVehicle,那么人们可以实现其所有方法并进行自定义.
这样做的目的IVehicle interface是确保这一点whenever you build a vehicle class, it reminds and forces you to make sure that you rightly build a vehicle
2.对于属性,界面是浪费时间吗?
不,绝对不是.
例如,每当您想要返回车速时,而不是仅仅将车速四舍五入到integer您想要的精确度floating point,
10 // public float currentSpeed { get; set; }
10.5 // public float currentSpeed { get {return {//write custom logic}; set; }
Run Code Online (Sandbox Code Playgroud)
Notice the customisation in Get accessor 的财产.
3.什么时候应该使用抽象类?
应该使用抽象类all derived class would be using some repeated method.例如,
public abstract Class AbstractClass
{
public virtual int Doors { get; set; }
public virtual int Wheels { get; set; }
public virtual Color VehicleColor { get; set; }
public virtual int TopSpeed { get; set; }
public virtual int HorsePower { get; set; }
public virtual int Cylinders { get; set; }
public string WhatSideDriving
{
if (Country == "US") return "Keep Right";
if (Country == "India") return "Keep Left";
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,该方法WhatSideDriving是already implemented并且可以由从此类派生的所有类使用.但是,可以覆盖其他成员,并且可以implemented根据所需的功能.
那么为什么我浪费时间创建一个接口如果我必须在我的类中声明My Interface的所有属性和功能.
因为界面就是这样; 一个(公共)接口.它没有定义实现,只定义用于与其任何实现接口的方法和属性.
当然,实现者称接口必须定义实现它.你还有什么期望这个呢?
也就是说,属性可以隐式(并且不可见)地实现为自动属性并不是不可思议,但是这对于方法不起作用,并且您通常需要更多get; set;,因此它将提供很少的好处(即,一个功能,不值得努力).
严格来说,声明接口是浪费时间。您可以跳过界面并节省一些时间。
然而,你可能走错了路。虽然这需要一些额外的时间和工作,但从长远来看,界面的价值是无价的。真正伟大的软件工程师的标志之一是能够很好地设计界面。
为了不那么抽象,接口的设计正是为了这个目的:形式化两种类之间的接口(换句话说,这两个类如何一起工作)。这有点像班级之间的合同,每个班级都说明他们承诺提供什么以及他们期望什么。例如,您的IVehicle示例发誓它将始终拥有一个名为 的属性doors。然后,任何可使用的代码都IVehicle可以信任 的所有实现IVehicle始终具有Doors. 现在,您可以安全地编写访问代码IVehicle.Doors,因为知道无论传递给此方法的特定实现是什么,您的代码都一定会工作 - 即使Vehicles包开发人员决定有一天添加一些您从未听说过或考虑过的车辆!
当您只有一个小类实现该接口,并且您是唯一的开发人员时,接口可能是多余的。但是,如果有多种车辆,每种车辆都有自己的逻辑和不同的成员,但必须由某些通用代码使用,该怎么办?例如,车辆跟踪管理器必须处理类Car、Truck等Plane。为什么不?他们都有速度和位置,这才是最重要的。
此外,当您让其他开发人员编写自己的车辆时,该界面是向他们展示必须如何执行此操作才能与您的其余代码配合使用的好方法。
同样,当您处理一个大型项目并将每个部分分配给不同的开发人员时,精心设计的界面可以确保这些程序员在相对隔离的情况下处理项目的不同部分,仍然可以创建一个可以正常工作的整体,这要归功于以下部分:很好地配合在一起。
同样,即使在您自己编码时,一个好的接口也是启动复杂类的好方法:它将帮助您跟踪需要实现的内容以及如何实现,但与更熟悉的技术规范不同,接口可以通过编译器,以便它可以在很多方面为您提供帮助(例如,当您想使用稍后将实现的类的部分内容编写逻辑时,可以从 IntelliSense 获得帮助)。
特别是在 C# 中,接口还有一个实际的好处。在 C# 中,您不能从多个类或抽象类继承(与 C++ 不同)。这样做是因为多重继承有时会让程序员的生活变得非常困难。但是您可以从多个接口继承,并且因为它们只是接口(没有实现),所以“多重继承”问题就不那么重要了。
最后,一个现实世界的例子:微软为您提供了一种List.Sort方法,可以帮助您对任何对象的列表进行排序。对于数字和字符串之类的东西来说显然很容易做到这一点,但也可以让它对你制作的任意对象(例如车辆)进行排序。但是 Microsoft 怎么可能知道您将实现什么类型的类,以及您打算如何对这些类进行排序?他们没有,但他们为您提供了一个名为 的界面IComparable。这定义了排序代码需要调用的方法,以便能够比较两个对象进行排序。如果你放入列表的对象实现了这个IComparable,你将告诉微软的List.Sort代码你的对象应该如何排序,现在你不再需要编写自己的排序函数,因为你可以使用精心设计、测试、记录和调试的微软一。
作为练习,尝试编写一个程序,该程序采用一个类列表Triangle(仅具有a、b、c存储每边长度的字段和一个CalculateArea方法),然后使用 Microsoft 的List.Sort. 不要编写自己的排序代码,也不要使用诸如 LINQ 之类的东西,而是通过制作ImplementOrderBy来完成。然后想一想:如果您是负责所有 .NET 库开发的项目经理,您将如何编写一个任何人都可以使用的排序函数,即使他们有自己奇怪的类?TriangleIComparable