我是一名刚刚接触 D 语言的 C# 程序员。我对 D 编程语言中的 OOP 有点困惑。
假设我有以下课程:
public class A {
protected void foo() {
writefln("A.foo() called.");
}
};
public class B : A {
public override void foo() {
writefln("B.foo() called.");
}
};
protected
修饰符意味着我可以仅在继承类上访问.foo()
方法。那么为什么这个D程序可以正常编译呢?
这是 C#.NET 中的等效项:
using System;
public class A {
protected virtual void foo() {
Console.WriteLine("a.foo() called.");
}
};
public class B : A {
public override void foo() {
Console.WriteLine("b.foo() called.");
}
};
public class MainClass {
public static void Main(string[] args) {
A a = new A();
B b = new B();
a.foo();
b.foo();
}
};
它无法编译并给出以下错误消息(如预期):
test.cs(10,30):错误CS0507:
protected'继承成员`A.foo()'B.foo()': cannot change access modifiers when overriding
有人可以解释一下这种 D 行为吗?
阻止覆盖是没有意义的。派生类可以实现允许访问的简单转发功能。考虑:
public class A {
protected virtual void foo() {
writefln("A.foo() called.");
}
};
public class B : A {
protected override void foo() { // OK
writefln("B.foo() called.");
}
public void call_foo() {
foo(); // But I allowed public access anyway!
}
};
因此,即使我没有重新定义
foo
的访问级别,我仍然允许公众访问它并且您对此无能为力。允许重新定义就更简单了。
因为对于“为什么这是可能的?”这个问题有一些很好的答案。我认为 C# 值得解释为什么它不可能:它是关于语言设计的“哲学”,可以归结为“is-a”与“has-a”的思想冲突。
C++ 都是关于“has-a”的思维,其中一些被传递给了 D 和 Java。 B 有方法
foo
,这对于编译器和程序员来说都是最重要的——而不是B是什么。在 C++ 中,甚至可以将方法重新声明为私有(或将类继承为私有),这意味着 A 的成员不会被 B 公开。
C# 是“is-a”概念的核心。因此,因为这里 B 实际上是 A,所以 B 中的所有内容都必须与 A 中的一样。编译器和程序员都不必担心更改,因为不可能更改。 B 始终是 A 的完美替代品。 “is-a”哲学禁止 C# 程序公开以前受保护的成员,尽管通过公共包装器实现这一点很简单。这没有什么意义,而且只是一个小小的不便——但对于保持语言哲学的一致性来说却是一件大事。
protected
函数可以重写为
protected
或public
,但不能重写为private
,并且public
函数只能重写为public
。我不知道为什么 C# 会限制
protected
,这样你就不能用
public
函数覆盖它。作为一个经常使用 C++、D 和 Java 进行编程但很少使用 C# 的人,这里选择 C# 对我来说没有什么意义。 C++、D 和 Java 都允许。