C#与Java中protected访问修饰符的差异

在面向对象编程中,访问修饰符是控制成员访问权限的重要机制。在C#和Java这两种流行的编程语言中,protected关键字用于定义成员的访问级别。尽管在很多情况下,这两个语言中的protected关键字行为相似,但它们在某些特定的上下文中却表现出微妙的差异。

在C#中,如果使用protected关键字标记一个字段,那么这个字段将对拥有它的类及其派生类可用。而在Java中,访问范围更广。不仅是拥有者和派生类可以访问该字段,同一包中的所有类也可以访问。在C#中,要实现类似的效果,可以使用protected internal访问级别。这样标记的成员具有internal(同一程序集)和protected级别的访问权限的联合。需要注意的是,Java的包和C#的程序集的概念并不等价。C#的程序集可以跨越多个命名空间,并且与物理单元(EXE、DLL)相关,它保存中间代码和元数据。Java的包更类似于C#中的命名空间,但关键的区别是它影响访问权限。

示例项目

以下是两个展示Java和C#中protected访问级别差异的项目。C#程序是在Visual Studio 2015 Community中创建的,目标是.NET 4.5.2。Java程序是在IntelliJ IDEA 15 Community Edition中创建的,设置为使用Java 8。Java/.NET的版本并不重要,这些项目没有什么特别的——完全可以在记事本中轻松完成,但如今能够免费获得如此出色的IDE,难道不令人兴奋吗?

Base.java

public class Base { protected int someProtectedField = 123; public void testAccessInBaseClass() { // 在Java和C#中的行为相同 System.out.println(someProtectedField); } }

Derived.java

public class Derived extends Base { public void testAccessInDerivedClass() { // 在Java和C#中的行为相同 System.out.println(someProtectedField); // 在Java中的行为不同 // 因为类在同一个包中,所以可以访问protected字段 System.out.println(new Base().someProtectedField); // 在C#中,字段必须是public或protected internal } }

NotDerived.java

public class NotDerived { public void testAccessInNotDerivedClass() { // 在Java中的行为不同 System.out.println(new Base().someProtectedField); // 在C#中,字段必须是public或protected internal } }

DerivedInAnotherPackage.java

import com.example.Base; public class DerivedInAnotherPackage extends Base { public void testAccessInDerivedClassFromAnotherPackage() { // 在Java和C#中的行为相同 System.out.println(someProtectedField); // 在Java中的行为不同 // 字段必须是public System.out.println(new Base().someProtectedField); } }

Base.cs

public class Base { protected int someProtectedField = 123; public void TestAccessInBaseClass() { // 在Java和C#中的行为相同 System.Console.WriteLine(someProtectedField); } }

Derived.cs

public class Derived : Base { public void TestAccessInDerivedClass() { // 在Java和C#中的行为相同 System.Console.WriteLine(someProtectedField); // 在C#中的行为不同 // 字段必须是public或protected internal System.Console.WriteLine(new Base().someProtectedField); } }

NotDerived.cs

public class NotDerived { public void TestAccessInNotDerivedClass() { // 在C#中的行为不同 System.Console.WriteLine(new Base().someProtectedField); } }

DerivedInAnotherAssembly.cs

using Protected; public class DerivedInAnotherAssembly : Base { public void TestAccessInDerivedClassFromAnotherAssembly() { // 在Java和C#中的行为相同 System.Console.WriteLine(someProtectedField); // 在C#中的行为不同 // 字段必须是public System.Console.WriteLine(new Base().someProtectedField); } }

希望代码中的注释能够清楚地解释一切,这个干燥的话题已经讨论得差不多了。刚刚为Arduino订购了一个USB盾牌,如果它工作正常,下一篇文章将是关于如何使用PlayStation控制器来控制它。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485