C# 为什么可以在任何地方覆盖和访问带有 protected 修饰符的函数?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10458142/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 13:57:47  来源:igfitidea点击:

Why a function with protected modifier can be overridden and accessible every where?

c#oopdaccess-modifiers

提问by Hyman

I'm C# programmer new to D language. I'm a bit to confused with OOP in D programming language.

我是 C# 程序员,刚接触 D 语言。我对 D 编程语言中的 OOP 有点困惑。

Assuming that I have the following class:

假设我有以下课程:

public class A {
   protected void foo() {
      writefln("A.foo() called.");
   }
};

public class B : A {
   public override void foo() {
      writefln("B.foo() called.");
   }
};

The protectedmodifier means that I can access the .foo()method just on inherited class,so why this Dprogram compiles normally?

protected修改意味着我可以访问.foo()只是继承类的方法,那么,为什么这个d程序正常编译?

Here is the equivalent to C#.NET:

这相当于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();
   }
};

It don't compiles and given the following error message(as I expected):

它不会编译并给出以下错误消息(如我所料):

test.cs(10,30): error CS0507: B.foo()': cannot change access modifiers when overridingprotected' inherited member `A.foo()'

test.cs(10,30):错误 CS0507:B.foo()': cannot change access modifiers when overriding受保护的'继承成员'A.foo()'

Can someone explain this D behavior? Thanks in advance.

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

采纳答案by Puppy

There's no purpose in preventing the override. The derived class could implement a trivial forwarding function that allows access. Consider:

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

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!
   }
};

Thus, even though I didn't redefine the access level of foo, I still allowed public access to it and there's nothing you can do about it. Allowing the redefinition is just simpler.

因此,即使我没有重新定义 的访问级别foo,我仍然允许公共访问它并且您无能为力。允许重新定义更简单。

回答by Jonathan M Davis

D's behavior in this matches Java's behavior. A derived class can give its function an access level which is less restrictive than the one on the function in the base class but not one which is more restrictive. So, a protectedfunction can be overridden as either protectedor public, but it can't be overridden as private, and a publicfunction can only be overridden as public.

D 在这方面的行为与 Java 的行为相匹配。派生类可以为其函数提供一个访问级别,该级别比基类中的函数的访问级别限制要少,但不是更严格的访问级别。因此,protected函数可以被覆盖为protectedor public,但不能被覆盖为private,并且public函数只能被覆盖为public

I have no idea why C# would restrict protectedsuch that you couldn't override it with a publicfunction. As someone who's programmed a great deal in C++, D, and Java but very little in C#, C#'s choice here makes very little sense to me. C++, D, and Java all allow it.

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

回答by Agent_L

Because there are some great answers to the the question "why it's possible?" I think C# deserves explanation why it's NOT possible: It's about the "philosophy" of a language design, and can be boiled down to "is-a" vs "has-a" clash of ideas.

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

C++ is all about "has-a" thinking, some of it was passed to D and Java. B hasmethod fooand this is most important for both the compiler and the programmer - not what B is. In C++ it's even possible to redeclare a method as private (or inherit class as private) which means that a member of A will NOT be exposed by B.

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

C# is hardcore about "is-a" concept. Therefore because here B actually isA, everything in B must be just like in A. Neither compiler nor the programmer have to worry about changes, because no changes are possible. B always is a perfect drop-in replacement for A.

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

The "is-a" philosophy forbids C# program from publicising previously protected member, even though it's trivial to do it via a public wrapper. It makes little sense and is just a small inconvenience here - but it's a big deal in keeping the language philosophy consistent.

“is-a”哲学禁止 C# 程序公开以前受保护的成员,即使通过公共包装器执行此操作是微不足道的。这没什么意义,只是这里的一个小不便 - 但保持语言哲学的一致性是一件大事。