现在我正在研究接口,无法理解接口实现之类的东西。例如我有一些代码:
IModelDoc2 swModel; //IModelDoc2 is an interface. What are we doing here?
boolstatus = swModel.Extension.SelectByID2(.....); //Some parameters
我不明白我们如何通过从接口调用来实现这个方法。类可以实现接口,我们可以从类中调用方法。正确的?但是我们如何从接口实现方法呢?
接口成员有两种实现方式:显式和隐式:
明确的:http: //msdn.microsoft.com/en-us/library/aa288461%28v=vs.71%29.aspx
隐式:http: //msdn.microsoft.com/en-us/library/aa664590%28v=vs.71%29.aspx
显式的明显好处是:如果某个变量/成员的编译时类型(声明的类型)是实现接口的类,则不能直接调用显式实现的成员,则需要接口引用来执行此操作。但是您不应该尝试将类或结构变量强制转换为接口类型。相反,您应该正确使用界面使用模式。接口是一个强大的抽象工具,它允许在知道实现的情况下抽象一些代码。这意味着这部分代码应该与实现无关,并且永远不会接收实现接口的结构对象的类引用,它应该只接收接口指针:
interface MyInterface {
void MyMethod(/*...*/);
int MyOtherMethod(/*...*/);
string MyProperty { get; set; }
}
class MyImplementation : MyInterface {
// explicit implementations:
void MyInterface.MyMethod (/*...*/) { /* ... */ }
string MyInterface.MyProperty { get { return /*...*/; } set { something = value; /*...*/ } }
// or even implicit:
public int MyOtherMethod(/*...*/) { /* ... */ return /*...*/; }
// Now, even you may have some public (better be internal) members,
// they should not be used in implementation-agnostic code
internal void SomeNonInterfaceMethod(/*...*/) { /*...*/ }
}
//...
MyInterface myImplementation = new MyImplementation(/*...*/);
// NOT MyInterface myImplementation = new MyImplementation(/*...*/);
//...
//some implementation-agnostic method:
void SomeUsingMethod(MyInterface implementation) { // NOT MyImplementation implementation
// it would kill the abstraction
implementation.MyMethod(/*...*/);
implementation.MyProperty = "some value";
// but you cannot call
// implementation.SomeNonInterfaceMethod(/*...*/); // won't work
// if somewhere you need to do this
MyImplementation violatedEncapsulationImplementation = (MyImplementation)implementation; // AVOID IT!
violatedEncapsulationImplementation.SomeNonInterfaceMethod(/*...*/); // AVOID IT!
// it would work, but it would be an indication of wrong code design
}
现在,您知道基本概念了。
所有的接口......以其最简单的形式......是一个类的实现。接口提供的一大好处(对我来说)是解耦你的代码......本质上它使你的代码更少依赖于其他类。
示例情况。
假设您有 3 种不同的货币,美元、印度卢比和欧元。如果没有接口,您将拥有此代码。
UsDollar currency1 = new UsDollar();
与各自的班级一起工作。如果您想将 UsDollar 换成卢比,则必须换出代码/进行任何必要的更改以支持下一个课程
Rupee currency1 = new Rupee();
但是通过使用接口,您可以解耦对正在使用的特定类的依赖,并改用接口(类似于您发布的示例代码段)。
所以假设你有一个实现 CurrencyValue 整数和 Exchange Rate 方法的接口
public interface ICurrency
{
int CurrencyValue { get; set; }
void ExchangeRate(double percent);
}
然后,您将拥有以下 3 个从接口继承的类。请记住,如果一个类继承自该接口,则它们必须实现与该接口实现的相同。
public class UsDollar : ICurrency
{
public int CurrencyValue { get; set; }
public void ExchangeRate(double percent)
{
Console.WriteLine("Your Exchange Rate for Us Dollar is {0}", CurrencyValue * percent);
}
}
public class Euro : ICurrency
{
public int CurrencyValue { get; set; }
public void ExchangeRate(double percent)
{
Console.WriteLine("Your Exchange Rate for Euro is {0}", CurrencyValue * percent);
}
}
public class Rupee : ICurrency
{
public int CurrencyValue { get; set; }
public void ExchangeRate(double percent)
{
Console.WriteLine("Your Exchange Rate for Rupee is {0}", CurrencyValue * percent);
}
}
所以通过改变你的用法
Rupee currency1 = new Rupee();
至
ICurrency currency1 = new Rupee();
您使用此类的代码不再关心它是卢比、美元、欧元……还是您最终创建的任何其他货币类别。
接口也可以在各种设计模式(因子模式)中提供价值。
示例用法:
ICurrency currency1 = new UsDollar();
ICurrency currency2 = new Euro();
ICurrency currency3 = new Rupee();
currency1.CurrencyValue = 10;
currency2.CurrencyValue = 13;
currency3.CurrencyValue = 16;
currency1.ExchangeRate(1.1);
currency2.ExchangeRate(1.6);
currency3.ExchangeRate(1.5);
所以回答你的问题
IModelDoc2 swModel; //IModelDoc2 is an interface. What are we doing here?
这应该专门创建某种类类型的新对象(在我的示例中,这与 ICurrency currency1 = new UsDollar(); 相同)。因此,在您的代码中的某处,您可以将值分配给 swModel,这将是从 IModelDoc2 继承的某个类/类型。
希望这对您有所帮助/澄清。
但是要阅读接口,我建议使用链接:
http://msdn.microsoft.com/en-us/library/87d83y5b%28v=vs.80%29.aspx
您必须了解多态性才能理解调用代码所看到的内容与实际实现所完成的内容之间的区别。
实现必须有一个实现该接口的实际类(忽略边缘情况)。
调用可能只看到一个接口,但该变量的实际类型必须是实现该接口的某个类。
你的例子:
IModelDoc2 swModel; //IModelDoc2 is an interface. What are we doing here?
boolstatus = swModel.Extension.SelectByID2(.....); //Some parameters
甚至不会编译,因为swModel
未初始化。
正确的代码是
IModelDoc2 swModel = new SomeClassImplementingIModelDoc2();
boolstatus = swModel.Extension.SelectByID2(.....); //Some parameters