接上一讲→C#接口
Virtual的实现接口成员
▢ 隐式实现的接口成员默认是sealed。
▲ 什么是隐式实现的接口成员
public class Parent : IFoo, IBar
{
//隐式实现
public void Do()
{
Console.WriteLine("Foo");
}//显式实现
int IBar.Do()
{
Console.WriteLine("Bar");
return 0;
}
}
▢ 如果想要进行重写的话,必须在基类中把成员标记为virtual或者abstract。
public interface IUndoable{void Undo();}
public class TextBox:IUndoable
{
public virtual void Undo()=>Console.WriteLine("TextBox.Undo");
}public class RichTextBox:TextBox
{
public override void Undo()=>Console.WriteLine("RichTextBox.Undo");
}
☆ 其实你不用virtual 、override也能运行,但是子类的这种行为相当于隐藏父类的方法。
直接重写:
namespace 隐式实现接口成员
{
public interface IFoo
{
void Do();
}public class Parent : IFoo
{
public void Do() => Console.WriteLine("Parent");
}public class Child : Parent
{
public void Do() => Console.WriteLine("Child");
}
class Program
{
static void Main(string[] args)
{
Child c = new Child();
c.Do();
((Parent)c).Do();
((IFoo)c).Do();
Console.Read();
}
}
}
输出:
Child
Parent
Parent
virtual 、override后重写:
namespace 隐式实现接口成员2
{
public interface IFoo
{
void Do();
}public class Parent : IFoo
{
public virtual void Do() => Console.WriteLine("Parent");
}public class Child : Parent
{
public override void Do() => Console.WriteLine("Child");
}
class Program
{
static void Main(string[] args)
{
Child c = new Child();
c.Do();
((Parent)c).Do();
((IFoo)c).Do();
Console.Read();
}
}
}
输出:
Child
Child
Child
★ 你可以认为例1是三级架构,当你写了virtual 、override,是二级架构
显式实现的接口不可以被标记为virtual,也不可以通过寻常的方式来重写,但是可以对其进行重新实现。
重新实现是指 → 子类:父类,接口
重新实现适用于重写显式实现的接口成员:
public interface IUndoable{void Undo();}
public class TextBox:IUndoable
{
void IUndoable.Undo()=>Console.WriteLine("TextBox.Undo");
}public class RichTextBox:TextBox,IUndoable
{
protected override void Undo()=>Console.WriteLine("RichTextBox.Undo");
}
具体实例:
namespace 显式实现接口成员
{
public interface IFoo
{
void Do();
}public class Parent : IFoo
{
void IFoo.Do() => Console.WriteLine("Parent");
}public class Child : Parent, IFoo
{
public void Do() => Console.WriteLine("Child");
}
class Program
{
static void Main(string[] args)
{
Child c = new Child();
c.Do();
((IFoo)c).Do();
Console.Read();
}
}
}
输出:
Child
Child
重新实现接口的替代方案
即使是显式实现的接口,接口的重新实现也可能有一些问题:
▢ 子类无法调用基类的方法
▢ 基类的开发人员没有预见到方法会被重新实现,并且可能不允许潜在的后果
设计一个无需重新实现的基类:
▢ 隐式实现成员的时候,按需标记virtual
▢ 显式实现成员的时候,可以这样做:
public class TextBox:IUndoable
{
void IUndoable.Undo()=>Undo();
protected virtual void Undo()=>Console.WriteLine("TextBox.Undo");
}public class RichTextBox:TextBox
{
protected override void Undo()=>Console.WriteLine("RichTextBox.Undo");
}
这种类似裹脚布的做法,都是为了满足部分奇葩需求搞的。
没事别去重新实现别人定义的显式实现方法,
因为,定义成显式就是为了 不要随便用它。
接口与装箱
▢ 把struct转化为接口会导致装箱
▢ 调用struct上隐式实现的成员不会导致装箱
interface I{void Foo();}
struct S:I{public void Foo(){}}
...
S s=new S();
s.Foo(); //No BoxingI i=s; // Box occurs when casting to interface
i.Foo();