无法访问派生类中的受保护方法
Posted
技术标签:
【中文标题】无法访问派生类中的受保护方法【英文标题】:Unable to access protected method in derived class 【发布时间】:2017-12-14 22:55:17 【问题描述】:我不明白为什么这段代码会给我一个 Intellisense 错误。
public abstract class Node
protected abstract string ToText();
public class htmlNode : Node
public List<Node> ChildNodes get; set;
protected override string ToText()
StringBuilder builder = new StringBuilder();
foreach (var node in ChildNodes)
builder.Append(node.ToText()); // <=== THIS IS THE ERROR
return builder.ToString();
在上面指出的那一行,我得到了错误:
错误 CS1540:无法通过“Node”类型的限定符访问受保护的成员“Node.ToText()”;限定符必须是“HtmlNode”类型(或派生自它)
HtmlNode
派生自Node
,那么为什么HtmlNode
不能访问Node
的受保护成员?
我将如何修改代码以使用 "a qualifier of type HtmlNode
",如错误消息中所建议的那样?
【问题讨论】:
问题是子节点列表是抽象节点的列表。那没有意义。抽象 Node 类必须像在 HTMLNODE 类中那样实现。要查看它的工作情况,请将子节点更改为 ListNode
的子类,并且应该能够访问所有这些子类都通用的方法。您的解决方法仅适用于 HtmlNode
类型的节点。这不是我需要的。
@AzarShaikh 如果node
不是HtmlNode
,那么它将崩溃。
我在这里发现了类似的问题:***.com/questions/13683324/…
@JohnPeters:但是HtmlNode
是实现抽象的类。为什么派生类不能访问基类的受保护成员?
【参考方案1】:
在我看来,您可以通过继承机制访问受保护的成员,但您仍然不能通过实例访问受保护的成员。
根据 MSDN,protected
关键字的含义如下:
protected
- 访问仅限于包含类或从包含类派生的类型。
现在,让我们假设编译器允许您编译它,现在您正在遍历您的集合并调用 .ToText()
方法。
如果node
是HtmlNode
或其子类,那么您可以调用此方法。
但是,如果node
是某种类型的AnotherNode
:
public class AnotherNode : Node
protected override string ToText()
在这种情况下,您正在尝试调用 AnotherNode
类的 protected ToText
方法。
你是“包含类(AnotherNode)”吗?没有。
你是“从另一个节点派生的类型”吗?没有。
因此,您似乎无法访问此方法。
由于ChildNodes
是编译时未知类型的实例,编译器无法确定您是否应该有权访问其方法。
这就是我看到编译器抛出这个异常的原因。
【讨论】:
我想这就是答案。当我用 C++ 编程时,我记得这非常好。如果它在 C# 中被允许,那将会很有用。【参考方案2】:您需要在派生类中为ToText()
方法提供实现,但您在实现中调用基类ToText()
方法,这没有意义。想象一下,你试过了,这也行不通:
public class HtmlNode : Node
protected override string ToText()
base.ToText(); // Will not compile: Cannot call abstract base member
如果您使用HtmlNode
类,事情会变得更加清晰。所以让我们使用它:
HtmlNode node = new HtmlNode();
node.ChildNodes.Add(new HtmlNode());
node.ChildNodes.Add(new NodeB()); // Say NodeB inherits Node
HtmlNode
调用NodeB
的ToText()
方法有意义吗?不,不是因为HtmlNode
没有继承NodeB
那么为什么要允许它访问NodeB
的protected
方法?
【讨论】:
这就是虚函数的用途。这很有意义。 @JonathanWood 但它不是虚拟的。它是抽象的。在 C# 中,它们的处理方式不同。 抽象方法是自动虚拟的。否则,就没有办法实现它们。 @JonathanWood 很公平,是的,你说得对,抽象方法是虚拟的。但是必须实现抽象方法,并且在实现它们时,不能调用它。这没有任何意义。 @JonathanWood CodingYoshi 写道:“base.ToText(); // 不会编译:无法调用抽象基成员”——这是一个完全不同的问题,编译时 i> 对未定义函数的引用。继承方式不一样。编译器可以接受 OP 的代码,它会运行和工作正常,但这是一个权限问题,正如 Yeldar Kurmangaliyev 和 Eric Lippert 在 ashin 的已删除(不知道为什么)答案中的链接中所解释的那样:blogs.msdn.microsoft.com/ericlippert/2010/01/14/…以上是关于无法访问派生类中的受保护方法的主要内容,如果未能解决你的问题,请参考以下文章