接口重新实现的替代方案
Alternatives to interface reimplementation
我正在阅读 Joe Albahari 出色的“C# 9 in a Nutshell”中的以下摘录,并试图理解此处以粗体显示的内容。有谁能以我能更好理解的方式解释替代方法吗?出于某种原因,这对我来说似乎有些落后。
Alternatives to interface reimplementation
Even with explicit member implementation, interface reimplementation is problematic for a couple of reasons:
The subclass has no way to call the base class method.
The base class author might not anticipate that a method be reimplemented and might not allow for the potential consequences.
Reimplementation can be a good last resort when subclassing hasn’t been anticipated. A better option, however, is to design a base class such that reimplementation will never be required. There are two ways to achieve this:
When implicitly implementing a member, mark it virtual if appropriate.
When explicitly implementing a member, use the following pattern if you anticipate that subclasses might need to override any logic:
public class TextBox : IUndoable
{
void IUndoable.Undo() => Undo(); // Calls method below
protected virtual void Undo() => Console.WriteLine ("TextBox.Undo");
}
public class RichTextBox : TextBox
{
protected override void Undo() => Console.WriteLine("RichTextBox.Undo");
}
If you don’t anticipate any subclassing, you can mark the class as sealed to preempt interface reimplementation.
据我了解,作者想说的是,与其隐藏基class的成员,不如覆盖它们。隐藏是指子 class 有一个具有相同签名的成员,但它在基 class 中没有标记为虚拟。
即如果 ParentClass 有方法 A();如果您希望它被 ChildClass 覆盖,请将 A() 设为虚方法。或者,如果您不希望 A() 被覆盖,请引入一个受保护的方法,该 A() 将使用该受保护的方法并使该受保护的方法成为虚拟的,以便子代在需要时可以覆盖。
希望这能回答您的问题。
所描述的问题是,当基 class 实现接口时,基 class 可能会发生某些行为。
文本框撤销的例子。假设基础文本框做了一些重要的(或者可能是实际的工作)用于撤销。
同样为了举例,假设作者在写baseclass的时候并没有想到继承classes(这里是richtextbox)
他本可以写成
public class TextBox : IUndoable
{
void IUndoable.Undo() => ....... undo logic here
}
任何继承 class 的都不能直接调用 Undo
(他们必须将其基数转换为 IUndoable
)
现在的问题是,当其他代码使用 IUndo 实现(例如菜单项)时,不会调用基础 class 中的重要撤消,除非继承 class 明确地执行此操作
还是一样:
public class TextBox : IUndoable
{
public void Undo() => ...... undo logic here
}
继承(RichTextBox)class、可以在显式实现撤消时调用其基类,但不确定。
如果 RichTextBox 自己做 Undo 并隐藏基础 Undo,则没有调用基础 Undo 的直接冲动(尽管比第一个选项更重要)
最后,基础class作者想要的是,当外部代码调用IUndoable.Undo
方法时,总是调用所需的代码。
(旁注:在一个抽象的 class 中,可以以不同的方式处理,但这是一个可以直接使用的 class,可能会或可能不会被继承)
将隐式实现虚拟化会有所帮助:
public class TextBox : IUndoable
{
public virtual void Undo() => ...... undo logic here
}
一旦继承 class 重写该方法,默认代码段也会调用基 class,但前提是使用了该代码段,并且仍会调用 base.Undo , 将选择权留给继承人。
这给出了您包含的最后一个示例:
public class TextBox : IUndoable
{
void IUndoable.Undo() => Undo(); // Calls method below
protected virtual void Undo() => Console.WriteLine ("TextBox.Undo");
}
这为继承 classes 提供了一个更安全的选项来实现他们自己的撤销,而不会丢失基础 class 的撤销(除非继承 class 明确实现 IUndoable
也一样,但我们不要去那里 :P )
在 richtextbox 示例中,撤消被覆盖,但基本撤消未被调用。正是这种情况可能导致 'undo' 的基本 class 实现被跳过。
但是在这里,如果某些东西(例如菜单项)调用了 IUndoable
的 Undo
,则显式实现被调用,强制要求的基础 class 撤消功能变为 运行,而且继承 class (richtextbox)
的覆盖实现
Is anyone able to explain the alternative approach in a way that I can
understand better?
它只是说,如果您尝试执行我的以下代码,它将无法编译。
那么如果你需要使用显式接口实现你该怎么办和一个继承class需要改变[=22= 】 那行为?好吧,您使用问题中提到的 exact 代码。它允许您使用显式接口实现并且允许它被覆盖。
就是这样。这就是它所说的全部内容。
using System;
public interface IUndoable {
void Undo();
}
public class TextBox : IUndoable
{
void IUndoable.Undo() => Console.WriteLine ("TextBox.Undo");
}
public class RichTextBox : TextBox
{
void IUndoable.Undo() => Console.WriteLine ("RichTextBox.Undo");
}
public class Program
{
public static void Main()
{
}
}
我正在阅读 Joe Albahari 出色的“C# 9 in a Nutshell”中的以下摘录,并试图理解此处以粗体显示的内容。有谁能以我能更好理解的方式解释替代方法吗?出于某种原因,这对我来说似乎有些落后。
Alternatives to interface reimplementation Even with explicit member implementation, interface reimplementation is problematic for a couple of reasons:
The subclass has no way to call the base class method.
The base class author might not anticipate that a method be reimplemented and might not allow for the potential consequences.
Reimplementation can be a good last resort when subclassing hasn’t been anticipated. A better option, however, is to design a base class such that reimplementation will never be required. There are two ways to achieve this:
When implicitly implementing a member, mark it virtual if appropriate.
When explicitly implementing a member, use the following pattern if you anticipate that subclasses might need to override any logic:
public class TextBox : IUndoable { void IUndoable.Undo() => Undo(); // Calls method below protected virtual void Undo() => Console.WriteLine ("TextBox.Undo"); } public class RichTextBox : TextBox { protected override void Undo() => Console.WriteLine("RichTextBox.Undo"); }
If you don’t anticipate any subclassing, you can mark the class as sealed to preempt interface reimplementation.
据我了解,作者想说的是,与其隐藏基class的成员,不如覆盖它们。隐藏是指子 class 有一个具有相同签名的成员,但它在基 class 中没有标记为虚拟。 即如果 ParentClass 有方法 A();如果您希望它被 ChildClass 覆盖,请将 A() 设为虚方法。或者,如果您不希望 A() 被覆盖,请引入一个受保护的方法,该 A() 将使用该受保护的方法并使该受保护的方法成为虚拟的,以便子代在需要时可以覆盖。 希望这能回答您的问题。
所描述的问题是,当基 class 实现接口时,基 class 可能会发生某些行为。
文本框撤销的例子。假设基础文本框做了一些重要的(或者可能是实际的工作)用于撤销。 同样为了举例,假设作者在写baseclass的时候并没有想到继承classes(这里是richtextbox)
他本可以写成
public class TextBox : IUndoable
{
void IUndoable.Undo() => ....... undo logic here
}
任何继承 class 的都不能直接调用 Undo
(他们必须将其基数转换为 IUndoable
)
现在的问题是,当其他代码使用 IUndo 实现(例如菜单项)时,不会调用基础 class 中的重要撤消,除非继承 class 明确地执行此操作
还是一样:
public class TextBox : IUndoable
{
public void Undo() => ...... undo logic here
}
继承(RichTextBox)class、可以在显式实现撤消时调用其基类,但不确定。 如果 RichTextBox 自己做 Undo 并隐藏基础 Undo,则没有调用基础 Undo 的直接冲动(尽管比第一个选项更重要)
最后,基础class作者想要的是,当外部代码调用IUndoable.Undo
方法时,总是调用所需的代码。
(旁注:在一个抽象的 class 中,可以以不同的方式处理,但这是一个可以直接使用的 class,可能会或可能不会被继承)
将隐式实现虚拟化会有所帮助:
public class TextBox : IUndoable
{
public virtual void Undo() => ...... undo logic here
}
一旦继承 class 重写该方法,默认代码段也会调用基 class,但前提是使用了该代码段,并且仍会调用 base.Undo , 将选择权留给继承人。
这给出了您包含的最后一个示例:
public class TextBox : IUndoable
{
void IUndoable.Undo() => Undo(); // Calls method below
protected virtual void Undo() => Console.WriteLine ("TextBox.Undo");
}
这为继承 classes 提供了一个更安全的选项来实现他们自己的撤销,而不会丢失基础 class 的撤销(除非继承 class 明确实现 IUndoable
也一样,但我们不要去那里 :P )
在 richtextbox 示例中,撤消被覆盖,但基本撤消未被调用。正是这种情况可能导致 'undo' 的基本 class 实现被跳过。
但是在这里,如果某些东西(例如菜单项)调用了 IUndoable
的 Undo
,则显式实现被调用,强制要求的基础 class 撤消功能变为 运行,而且继承 class (richtextbox)
Is anyone able to explain the alternative approach in a way that I can understand better?
它只是说,如果您尝试执行我的以下代码,它将无法编译。
那么如果你需要使用显式接口实现你该怎么办和一个继承class需要改变[=22= 】 那行为?好吧,您使用问题中提到的 exact 代码。它允许您使用显式接口实现并且允许它被覆盖。
就是这样。这就是它所说的全部内容。
using System;
public interface IUndoable {
void Undo();
}
public class TextBox : IUndoable
{
void IUndoable.Undo() => Console.WriteLine ("TextBox.Undo");
}
public class RichTextBox : TextBox
{
void IUndoable.Undo() => Console.WriteLine ("RichTextBox.Undo");
}
public class Program
{
public static void Main()
{
}
}