您的位置:首页 > 产品设计 > UI/UE

Effective C#之20:Distinguish Between Implementing Interfaces and Overriding Virtual Functions

2008-10-19 19:31 387 查看
Item 20: Distinguish Between
Implementing Interfaces and Overriding Virtual Functions


区分实现接口和重写虚方法

At first
glance, implementing an interface seems to be the same as overriding avirtual
function. You provide a definition for a member that has been declared in
another type. That first glance is very deceiving. Implementing an interface is
very different from overriding a virtual function. Members declared in
interfaces are not virtual at least, not by default.

从第一眼来看,实现接口和重写虚函数看起来是一样的。你为已经在其它类型里面声明的成员提供一个定义。第一眼是很有欺骗性的。实现接口和重写虚方法很不同。在接口里声明的成员至少不是虚的,默认就不是。

Derived
classes cannot override an interface member implemented in a base class.
Interfaces can be explicitly implemented, which hides them from a class's
public interface. They are different concepts with different uses.

派生类不能重写在基类里面实现的接口成员。接口能够被显式的实现,这将它们从类的公共接口隐藏起来了。它们是有不同的应用的不同概念。

But you
can implement interfaces in such a manner that derived classes can modify your
implementation. You just have to create hooks for derived classes.

但是你可以以这样的方式实现接口:派生类可以修改你的实现。你仅仅不得不为派生类创建钩子。

To
illustrate the differences, examine a simple interface and implementation of it
in one class:

为了描述该不同,看一个简单的接口和在一个类里面对它的实现: interface IMsg

{

void Message();

}

public class MyClass : IMsg

{

public void Message()

{

Console.WriteLine("MyClass");

}

}

The
Message() method is part of MyClass's public interface. Message can also be
accessed through the IMsg point that is part of the MyClass type. Now let's
complicate the situation a little by adding a derived class:

Message()方法是MyClass类公共接口的一部分。Message同样也能通过MyClass类型的IMsg来访问。现在,通过添加一个派生类来使情况变得复杂点。 public class MyDerivedClass : MyClass

{

public new void Message()

{

Console.WriteLine("MyDerivedClass");

}

}

Notice
that I had to add the new keyword to the definition of the previous Message
method (see Item 29). MyClass.Message() is not virtual. Derived classes cannot
provide an overridden version of Message. The MyDerived class creates a new
Message method, but that method does not override MyClass.Message: It hides it.
Furthermore, MyClass. Message is still available through the IMsg reference:

注意,我不得不向前面的Message方法添加一个new关键字(见Item29)。MyClass.Message()不是虚的。派生类不能提供Message的重写版本。MyDerived类创建了新的Message方法,这个方法没有重写MyClass.Message:隐藏了它。进一步来说,通过IMsg引用,MyClass.Message仍然可用。 MyDerivedClass d = new MyDerivedClass();

d.Message(); // prints "MyDerivedClass".

IMsg m = d as IMsg;

m.Message(); // prints "MyClass"

Interface
methods are not virtual. When you implement an interface, you are declaring a
concrete implementation of a particular contract in that type.

接口方法不是虚的。当你实现接口的时候,你正在声明一个那个类里面特殊约定的实现。

But you
often want to create interfaces, implement them in base classes, and modify the
behavior in derived classes. You can. You've got two options. If you do not
have access to the base class, you can reimplement the interface in the derived
class:

但是你经常要创建接口,在基类里面实现它们,在派生类里面修改它们的行为。你可以这样做。你有2个选择。你果你没有对基类的访问,可以在派生类里面重新实现接口。 public class MyDerivedClass : MyClass, IMsg

{

public new void Message()

{

Console.WriteLine("MyDerivedClass");

}

}

The
addition of the IMsg keyword changes the behavior of your derived class so that
IMsg.Message() now uses the derived class version:

添加了IMsg关键字,改变了派生类的行为,IMsg.Message()现在使用派生类的版本: MyDerivedClass d = new MyDerivedClass();

d.Message(); // prints "MyDerivedClass".

IMsg m = d as IMsg;

m.Message(); // prints "MyDerivedClass"

You
still need the new keyword on the MyDerivedClass.Message() method. That's your
clue that there are still problems (see Item 29). The base class version is
still accessible through a reference to the base class:

你仍然需要在MyDerivedClass.Message()方法上使用new关键字。如果仍然有问题的话,这就是你的线索(见Item 29)。基类的版本,仍然能够通过对基类的引用来访问。 MyDerivedClass d = new MyDerivedClass();

d.Message(); // prints "MyDerivedClass".

IMsg m = d as IMsg;

m.Message(); // prints "MyDerivedClass"

MyClass b = d;

b.Message(); // prints "MyClass"

The only
way to fix this problem is to modify the base class, declaring that the
interface methods should be virtual:

修复这个问题的唯一方法就是:修改基类,声明它的接口方法应该是虚的。

public class MyClass : IMsg

{

public virtual void Message()

{

Console.WriteLine("MyClass");

}

}

public class MyDerivedClass : MyClass

{

public override void Message()

{

Console.WriteLine("MyDerivedClass");

}

}

MyDerivedClass
and all classes derived from MyClass can declare their own methods for
Message(). The overridden version will be called every time: through the
MyDerivedClass reference, through the IMsg reference, and through the MyClass
reference.

MyDerivedClass类和所有MyClass的派生类声明自己的Message()方法。重写的版本每次都会被调用:通过MyDerivedClass引用,通过IMsg引用,通过MyClass引用。

If you
dislike the concept of impure virtual functions, just make one small change to
the definition of MyClass:

如果你讨厌非纯虚方法的概念,那么仅仅需要对MyClass的定义做个小小的修改。 public abstract class MyClass: IMsg

{

public abstract void Message();

}

Yes, you
can implement an interface without actually implementing the methods in that
interface. By declaring abstract versions of the methods in the interface, you
declare that all types derived from your type must implement that interface.
The IMsg interface is part of the declaration of MyClass, but defining the
methods is deferred to each derived class.

是的,不需要实际的实现接口上的方法,你可以实现一个接口。通过声明方法的abstract版本,你就声明了,从你的类型派生的所有类型必须实现该接口。IMsg接口是MyClass声明的一部分,但是定义该方法延迟给了每个派生类。

Explicit
interface implementation enables you to implement an interface, yet hide its
members from the public interface of your type. Its use throws a few other
twists into the relationships between implementing interfaces and overriding
virtual functions. You use explicit interface implementation to limit client
code from using the interface methods when a more appropriate version is
available. The IComparable idiom in Item 26 shows this in detail.

显式接口实现使你能够实现一个接口,还从你的类型的公共接口隐藏它的成员。它的使用,使得在实现接口和重写虚方法之间产生了一些别扭。当一个更合适的版本可用时,你使用显式接口实现来限制客户代码使用接口方法。Item 26里面的IComoarable习惯展示了这个细节。

Implementing
interfaces allows more options than creating and overriding virtual functions.
You can create sealed implementations, virtual implementations, or abstract
contracts for class hierarchies. You can decide exactly how and when derived
classes can modify the default behavior for members of any interface your class
implements. Interface methods are not virtual methods, but a separate contract.

实现接口比创建、重写虚方法允许更多的选择。你可以为类体系创建封闭的实现,虚实现,或者抽象约定。你可以准确的决定如何及何时,派生类能够修改你的类实现的任何接口方法的默认行为。接口方法不是虚方法,是一个单独的约定。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: