10

我是 C# 程序员,不熟悉 D 语言。我对 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: B.foo()': cannot change access modifiers when overridingprotected' 继承的成员 `A.foo()'

有人可以解释这种 D 行为吗?提前致谢。

4

3 回答 3

19

阻止覆盖没有任何目的。派生类可以实现一个允许访问的简单转发功能。考虑:

public class A {
    protected 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,我仍然允许公共访问它,您对此无能为力。允许重新定义更简单。

于 2012-05-05T01:57:46.810 回答
8

因为对于“为什么可能?”这个问题有一些很好的答案。我认为 C# 值得解释为什么它不可能:它是关于语言设计的“哲学”,可以归结为“is-a”与“has-a”的思想冲突。

C++ 完全是关于“有”的思想,其中一些被传递给了 D 和 Java。B方法foo,这对编译器和程序员来说都是最重要的——而不是 B 是什么。在 C++ 中,甚至可以将方法重新声明为私有(或将类继承为私有),这意味着 A 的成员不会被 B 公开。

C# 是关于“is-a”概念的核心。因此,因为这里的 B 实际上A,所以 B 中的所有内容都必须与 A 中的一样。编译器和程序员都不必担心更改,因为不可能更改。B 始终是 A 的完美替代品。

“is-a”哲学禁止 C# 程序公开以前受保护的成员,即使通过公共包装器来做这件事是微不足道的。这没有什么意义,在这里只是一个小小的不便 - 但在保持语言哲学的一致性方面很重要。

于 2013-08-22T11:41:51.617 回答
7

D 在这方面的行为与 Java 的行为相匹配。派生类可以为其函数赋予一个访问级别,该访问级别比基类中函数的访问级别限制更少,但限制级别更高。所以,一个protected函数可以被重写为protectedor public,但它不能被重写为private,并且一个public函数只能被重写为public

我不知道为什么 C# 会限制protected你不能用public函数覆盖它。作为一个使用 C++、D 和 Java 编写大量程序但很少使用 C# 的人,C# 的选择对我来说意义不大。C++、D 和 Java 都允许它。

于 2012-05-05T02:36:56.107 回答