标题:[.net基础]访问修饰符

一、前言

基础掌握不牢固啊,所以记录下来。

二、方法访问修饰符Internal

  (1)、创建工程ParentAndSon

  (2)、添加类ModelA

namespace ParentAndSon
{
public class ModelA
{
internal void TestInternal()
{
} protected void TestProtected()
{
} protected internal void TestProtectedInternal()
{
}
}
}

  (3)、添加测试类MainIn,注意命名空间和ModelA相同

namespace ParentAndSon
{
public class MainIn
{
public static void Main(string[] arg)
{
ModelA a = new ModelA();
a.TestInternal();
//a.TestProtected();
a.TestProtectedInternal();
}
}
}

  可看出,只有protected修饰的无法访问,internal和protected internal修饰的方法均可访问。

  (4)、添加测试类InvokeModelA,注意命名空间和ModelA不同

namespace SomeNameSpace
{
public class InvokeModelA
{
public InvokeModelA()
{
ModelA a = new ModelA();
a.TestInternal();
//a.TestProtected();
a.TestProtectedInternal();
}
}
}

  可看出,只有protected修饰的无法访问,internal和protected internal修饰的方法均可访问。

  (5)、创建新工程TestParentAndSon,以下操作均在TestParentAndSon项目中。

  (6)、添加测试类Program,注意命名空间和ModelA不同

namespace TestParentAndSon
{
class Program
{
static void Main(string[] args)
{
ModelA a = new ModelA();
//a.TestInternal();
//a.TestProtected();
//a.TestProtectedInternal();
}
}
}

  可看出,protected、internal和protected internal修饰的方法均不可访问。

  (7)、添加测试类TestA,注意命名空间和ModelA相同

namespace ParentAndSon
{
public class TestA
{
public TestA()
{
ModelA a = new ModelA();
//a.TestInternal();
//a.TestProtected();
//a.TestProtectedInternal();
}
}
}

  可看出,protected、internal和protected internal修饰的方法均不可访问。
  (8)、添加子类Son

namespace TestParentAndSon
{
public class Son : ModelA
{
public Son()
{
//this.TestInternal();
this.TestProtected();
this.TestProtectedInternal();
}
}
}

  可看出,internal修饰的方法不可访问,而protected和protected internal修饰的方法可以访问。

总结:

  internal修饰符是针对同一程序集的,如果是同一程序集,则可以访问,否则不可访问。

  protected是针对子类的,不管是否位于同一个程序集。

  protected internal是把两者的优点集合到一起了,范围比两者任何一个都大。

三、继承override和new

1、测试public修饰方法

A、方法签名和父类相同

  (1)、新建工程ParentAndSon

  (2)、添加类MA

namespace ParentAndSon
{
public class MA
{
public void InvokeShowProtected()
{
Console.WriteLine("MA-InvokeShowProtected");
} public void InvokeShowProtectedInternal()
{
Console.WriteLine("MA-InvokeShowProtectedInternal");
}
}
}

  (3)、添加子类MAA,方法签名和MA完全一样

namespace ParentAndSon
{
public class MAA : MA
{
public void InvokeShowProtected()
{
Console.WriteLine("MAA-InvokeShowProtected");
} public void InvokeShowProtectedInternal()
{
Console.WriteLine("MAA-InvokeShowProtectedInternal");
}
}
}

  (4)、添加子类MAAA,方法签名和MAA完全一样

namespace ParentAndSon
{
public class MAAA : MAA
{
public void InvokeShowProtected()
{
Console.WriteLine("MAAA-InvokeShowProtected");
} public void InvokeShowProtectedInternal()
{
Console.WriteLine("MAAA-InvokeShowProtectedInternal");
}
}
}

  (5)、添加测试类Programe

namespace ParentAndSon
{
public class Programe
{
public static void Main(string[] arg)
{
Console.WriteLine("MA a = new MA();");
MA a = new MA();
a.InvokeShowProtected();
a.InvokeShowProtectedInternal();
Console.WriteLine(); Console.WriteLine("MAA aa = new MAA();");
MAA aa = new MAA();
aa.InvokeShowProtected();
aa.InvokeShowProtectedInternal();
Console.WriteLine("MA b = (MA)aa;");
MA b = (MA)aa;
b.InvokeShowProtected();
b.InvokeShowProtectedInternal();
Console.WriteLine(); Console.WriteLine("MAAA aaa = new MAAA();");
MAAA aaa = new MAAA();
aaa.InvokeShowProtected();
aaa.InvokeShowProtectedInternal();
Console.WriteLine("MAA bb = (MAA)aaa;");
MAA bb = (MAA)aaa;
bb.InvokeShowProtected();
bb.InvokeShowProtectedInternal();
Console.WriteLine(); Console.WriteLine("MA na = new MAA();");
MA na = new MAA();
na.InvokeShowProtected();
na.InvokeShowProtectedInternal();
Console.WriteLine("MAA _na = (MAA)na;");
MAA _na = (MAA)na;
_na.InvokeShowProtected();
_na.InvokeShowProtectedInternal();
Console.WriteLine(); Console.WriteLine("MAA naa = new MAAA();");
MAA naa = new MAAA();
naa.InvokeShowProtected();
naa.InvokeShowProtectedInternal();
Console.WriteLine("MAAA _naa = (MAAA)naa;");
MAAA _naa = (MAAA)naa;
_naa.InvokeShowProtected();
_naa.InvokeShowProtectedInternal();
Console.WriteLine(); Console.ReadKey();
}
}
}

  (6)、执行结果

MA a = new MA();
MA-InvokeShowProtected
MA-InvokeShowProtectedInternal MAA aa = new MAA();
MAA-InvokeShowProtected
MAA-InvokeShowProtectedInternal
MA b = (MA)aa;
MA-InvokeShowProtected
MA-InvokeShowProtectedInternal MAAA aaa = new MAAA();
MAAA-InvokeShowProtected
MAAA-InvokeShowProtectedInternal
MAA bb = (MAA)aaa;
MAA-InvokeShowProtected
MAA-InvokeShowProtectedInternal MA na = new MAA();
MA-InvokeShowProtected
MA-InvokeShowProtectedInternal
MAA _na = (MAA)na;
MAA-InvokeShowProtected
MAA-InvokeShowProtectedInternal MAA naa = new MAAA();
MAA-InvokeShowProtected
MAA-InvokeShowProtectedInternal
MAAA _naa = (MAAA)naa;
MAAA-InvokeShowProtected
MAAA-InvokeShowProtectedInternal

B、方法修饰符改成new

步骤和上述一样,只是MAA:

namespace ParentAndSon
{
public class MAA : MA
{
public new void InvokeShowProtected()
{
Console.WriteLine("MAA-InvokeShowProtected");
} public new void InvokeShowProtectedInternal()
{
Console.WriteLine("MAA-InvokeShowProtectedInternal");
}
}
}

MAAA:

namespace ParentAndSon
{
public class MAAA : MAA
{
public new void InvokeShowProtected()
{
Console.WriteLine("MAAA-InvokeShowProtected");
} public new void InvokeShowProtectedInternal()
{
Console.WriteLine("MAAA-InvokeShowProtectedInternal");
}
}
}

执行结果和【A、方法签名和父类相同】一样。可见默认是new。

C、方法修饰符改成override

namespace ParentAndSon
{
public class MAA : MA
{
public override void InvokeShowProtected()
{
Console.WriteLine("MAA-InvokeShowProtected");
} public new void InvokeShowProtectedInternal()
{
Console.WriteLine("MAA-InvokeShowProtectedInternal");
}
}
}

编译出错:

Error        'ParentAndSon.MAA.InvokeShowProtected()': cannot override inherited member 'ParentAndSon.MA.InvokeShowProtected()' because it is not marked virtual, abstract, or override    D:\KiteSource\Temp\PageLoadAndOnload\ParentAndSon\MAA.cs            ParentAndSon

所以不能改成override。

2、测试public修饰方法(调用protected方法)

A、方法签名和父类相同

  (1)、新建工程ParentAndSon

  (2)、添加类MA

namespace ParentAndSon
{
public class MA
{
protected virtual void ShowProtected()
{
Console.WriteLine("MA-ShowProtected");
} protected internal virtual void ShowProtectedInternal()
{
Console.WriteLine("MA-ShowProtectedInternal");
} public void InvokeShowProtected()
{
this.ShowProtected();
} public void InvokeShowProtectedInternal()
{
this.ShowProtectedInternal();
}
}
}

  (3)、添加子类MAA,方法签名和MA完全一样

namespace ParentAndSon
{
public class MAA : MA
{
protected virtual void ShowProtected()
{
Console.WriteLine("MAA-ShowProtected");
} protected internal virtual void ShowProtectedInternal()
{
Console.WriteLine("MAA-ShowProtectedInternal");
} public void InvokeShowProtected()
{
this.ShowProtected();
} public void InvokeShowProtectedInternal()
{
this.ShowProtectedInternal();
}
}
}

  (4)、添加子类MAAA,方法签名和MAA完全一样

namespace ParentAndSon
{
public class MAAA : MAA
{
protected virtual void ShowProtected()
{
Console.WriteLine("MAAA-ShowProtected");
} protected internal virtual void ShowProtectedInternal()
{
Console.WriteLine("MAAA-ShowProtectedInternal");
} public void InvokeShowProtected()
{
this.ShowProtected();
} public void InvokeShowProtectedInternal()
{
this.ShowProtectedInternal();
}
}
}

  (5)、添加测试类Programe

namespace ParentAndSon
{
public class Programe
{
public static void Main(string[] arg)
{
Console.WriteLine("MA a = new MA();");
MA a = new MA();
a.InvokeShowProtected();
a.InvokeShowProtectedInternal();
Console.WriteLine(); Console.WriteLine("MAA aa = new MAA();");
MAA aa = new MAA();
aa.InvokeShowProtected();
aa.InvokeShowProtectedInternal();
Console.WriteLine("MA b = (MA)aa;");
MA b = (MA)aa;
b.InvokeShowProtected();
b.InvokeShowProtectedInternal();
Console.WriteLine(); Console.WriteLine("MAAA aaa = new MAAA();");
MAAA aaa = new MAAA();
aaa.InvokeShowProtected();
aaa.InvokeShowProtectedInternal();
Console.WriteLine("MAA bb = (MAA)aaa;");
MAA bb = (MAA)aaa;
bb.InvokeShowProtected();
bb.InvokeShowProtectedInternal();
Console.WriteLine(); Console.WriteLine("MA na = new MAA();");
MA na = new MAA();
na.InvokeShowProtected();
na.InvokeShowProtectedInternal();
Console.WriteLine("MAA _na = (MAA)na;");
MAA _na = (MAA)na;
_na.InvokeShowProtected();
_na.InvokeShowProtectedInternal();
Console.WriteLine(); Console.WriteLine("MAA naa = new MAAA();");
MAA naa = new MAAA();
naa.InvokeShowProtected();
naa.InvokeShowProtectedInternal();
Console.WriteLine("MAAA _naa = (MAAA)naa;");
MAAA _naa = (MAAA)naa;
_naa.InvokeShowProtected();
_naa.InvokeShowProtectedInternal();
Console.WriteLine(); Console.ReadKey();
}
}
}

  (6)、执行结果

MAA-ShowProtectedInternal
MA b = (MA)aa;
MA-ShowProtected
MA-ShowProtectedInternal MAAA aaa = new MAAA();
MAAA-ShowProtected
MAAA-ShowProtectedInternal
MAA bb = (MAA)aaa;
MAA-ShowProtected
MAA-ShowProtectedInternal MA na = new MAA();
MA-ShowProtected
MA-ShowProtectedInternal
MAA _na = (MAA)na;
MAA-ShowProtected
MAA-ShowProtectedInternal MAA naa = new MAAA();
MAA-ShowProtected
MAA-ShowProtectedInternal
MAAA _naa = (MAAA)naa;
MAAA-ShowProtected
MAAA-ShowProtectedInternal

B、(public)方法修饰符改成new

步骤和上述一样,只是MAA:

namespace ParentAndSon
{
public class MAA : MA
{
protected virtual void ShowProtected()
{
Console.WriteLine("MAA-ShowProtected");
} protected internal virtual void ShowProtectedInternal()
{
Console.WriteLine("MAA-ShowProtectedInternal");
} public new void InvokeShowProtected()
{
this.ShowProtected();
} public new void InvokeShowProtectedInternal()
{
this.ShowProtectedInternal();
}
}
}

MAAA:

namespace ParentAndSon
{
public class MAAA : MAA
{
protected virtual void ShowProtected()
{
Console.WriteLine("MAAA-ShowProtected");
} protected internal virtual void ShowProtectedInternal()
{
Console.WriteLine("MAAA-ShowProtectedInternal");
} public new void InvokeShowProtected()
{
this.ShowProtected();
} public new void InvokeShowProtectedInternal()
{
this.ShowProtectedInternal();
}
}
}

执行结果和【A、方法签名和父类相同】执行结果一样。说明默认是new的。

C、(public)方法修饰符改成override

其他代码不变,只是MAA变了:

public override void InvokeShowProtected()
{
this.ShowProtected();
} public override void InvokeShowProtectedInternal()
{
this.ShowProtectedInternal();
}

编译不通过,提示:

Error        'ParentAndSon.MAA.InvokeShowProtectedInternal()': cannot override inherited member 'ParentAndSon.MA.InvokeShowProtectedInternal()' because it is not marked virtual, abstract, or override    D:\KiteSource\Temp\PageLoadAndOnload\ParentAndSon\MAA.cs            ParentAndSon

MAAA也是一样。

1和2说明,protected和protected internal和public修饰符在父类和子类方法覆盖上面,效果是一样的,经测试public virtual和public的表现也是一样的。

3、测试virtual方法

A、方法签名和父类相同

  (1)、新建工程ParentAndSon

  (2)、添加MA类

public class MA
{
public virtual void InvokeShowProtected()
{
Console.WriteLine("MA-InvokeShowProtected");
}
}

  (3)、添加子类MAA

public class MAA : MA
{
public virtual void InvokeShowProtected()
{
Console.WriteLine("MAA-InvokeShowProtected");
}
}

  (4)、添加子类MAAA

public class MAAA : MAA
{
public virtual void InvokeShowProtected()
{
Console.WriteLine("MAAA-InvokeShowProtected");
}
}

  (5)、测试程序

public static void Main(string[] arg)
{
Console.WriteLine("MA a = new MA();");
MA a = new MA();
a.InvokeShowProtected();
Console.WriteLine(); Console.WriteLine("MAA aa = new MAA();");
MAA aa = new MAA();
aa.InvokeShowProtected();
Console.WriteLine("MA b = (MA)aa;");
MA b = (MA)aa;
b.InvokeShowProtected();
Console.WriteLine(); Console.WriteLine("MAAA aaa = new MAAA();");
MAAA aaa = new MAAA();
aaa.InvokeShowProtected();
Console.WriteLine("MAA bb = (MAA)aaa;");
MAA bb = (MAA)aaa;
bb.InvokeShowProtected();
Console.WriteLine(); Console.WriteLine("MA na = new MAA();");
MA na = new MAA();
na.InvokeShowProtected();
Console.WriteLine("MAA _na = (MAA)na;");
MAA _na = (MAA)na;
_na.InvokeShowProtected();
Console.WriteLine(); Console.WriteLine("MAA naa = new MAAA();");
MAA naa = new MAAA();
naa.InvokeShowProtected();
Console.WriteLine("MAAA _naa = (MAAA)naa;");
MAAA _naa = (MAAA)naa;
_naa.InvokeShowProtected();
Console.WriteLine(); Console.ReadKey();
}

  (6)、执行结果

MA a = new MA();
MA-InvokeShowProtected MAA aa = new MAA();
MAA-InvokeShowProtected
MA b = (MA)aa;
MA-InvokeShowProtected MAAA aaa = new MAAA();
MAAA-InvokeShowProtected
MAA bb = (MAA)aaa;
MAA-InvokeShowProtected MA na = new MAA();
MA-InvokeShowProtected
MAA _na = (MAA)na;
MAA-InvokeShowProtected MAA naa = new MAAA();
MAA-InvokeShowProtected
MAAA _naa = (MAAA)naa;
MAAA-InvokeShowProtected

B、子类方法改用new

MA不变,MAA如下:

public class MAA : MA
{
public new void InvokeShowProtected()
{
Console.WriteLine("MAA-InvokeShowProtected");
}
}

MAAA如下:

public class MAAA : MAA
{
public new void InvokeShowProtected()
{
Console.WriteLine("MAAA-InvokeShowProtected");
}
}

测试程序不变,结果和【A、方法签名和父类相同】一样。

C、子类方法改用override

MA不变,MAA如下:

public class MAA : MA
{
public override void InvokeShowProtected()
{
Console.WriteLine("MAA-InvokeShowProtected");
}
}

MAAA如下:

public class MAAA : MAA
{
public override void InvokeShowProtected()
{
Console.WriteLine("MAAA-InvokeShowProtected");
}
}

测试程序不变,结果如下:

MA a = new MA();
MA-InvokeShowProtected MAA aa = new MAA();
MAA-InvokeShowProtected
MA b = (MA)aa;
MAA-InvokeShowProtected MAAA aaa = new MAAA();
MAAA-InvokeShowProtected
MAA bb = (MAA)aaa;
MAAA-InvokeShowProtected MA na = new MAA();
MAA-InvokeShowProtected
MAA _na = (MAA)na;
MAA-InvokeShowProtected MAA naa = new MAAA();
MAAA-InvokeShowProtected
MAAA _naa = (MAAA)naa;
MAAA-InvokeShowProtected

测试结果表明:

如果子类和父类方法签名一样,那么默认是new,也就是子类方法是另外一个新的方法,所以调用对象“表面”是哪个类型,就调用该类型的方法,而不管其“真实”类型是什么。但是需要注意如下写:

MA a = new MA();
MAA aaaddd = (MAA)a;
aaaddd.InvokeShowProtected();

会在运行时报类型转化错误。
而override则是完全覆盖父类方法,也就是无论“表面”是什么类型,都会执行其“真实”的方法。

参考:

C#中 protected internal 和 internal 的区别

访问修饰符(C# 编程指南)

4、注意点

当使用override覆盖父类方法时,要求方法签名和父类一模一样,只是改成override,访问修饰符要求完全一样,否则报错。比如

父类:

public class MA
{
protected virtual void InvokeShowProtected()
{
Console.WriteLine("MA-InvokeShowProtected");
}
}

子类:

public class MAA : MA
{
public override void InvokeShowProtected()
{
Console.WriteLine("MAA-InvokeShowProtected");
}
}

编译报错:

Error        'ParentAndSon.MAA.InvokeShowProtected()': cannot change access modifiers when overriding 'protected' inherited member 'ParentAndSon.MA.InvokeShowProtected()'    D:\KiteSource\Temp\PageLoadAndOnload\ParentAndSon\MAA.cs            ParentAndSon

但是new可以,因为new是一个完全新的方法,比如父类:

public class MA
{
protected virtual void InvokeShowProtected()
{
Console.WriteLine("MA-InvokeShowProtected");
}
}

子类:

public class MAA : MA
{
public new void InvokeShowProtected()
{
Console.WriteLine("MAA-InvokeShowProtected");
}
}

孙类:

public class MAAA : MAA
{
public new void InvokeShowProtected()
{
Console.WriteLine("MAAA-InvokeShowProtected");
}
}

可以正常调用。

参考:

为什么子类重写父类的方法的访问修饰符,不能低于父类的方法访问权限?

(2014-03-12 18:22)

[.net基础]访问修饰符的更多相关文章

  1. Java基础-访问修饰符

    访问修饰符 default (即缺省,什么也不写): 在同一包内可见,不使用任何修饰符.使用对象:类.接口.变量.方法. private : 在同一类内可见.使用对象:变量.方法. 注意:不能修饰类( ...

  2. C#基础访问修饰符概述

    前言: 在编写面向对象语言时我们时长离不开相关类型和成员的相关访问性,而访问性的关键则是取决于访问修饰符的声明,其作用是用于指定类型或成员的可访问性. 访问修饰符的六种可访问性级别: public:共 ...

  3. C#基础回顾(一)—C#访问修饰符

    一.写在前面的话 好久没有停下来总结自己,转眼间15年过去好些天,回首过去的日子,亦或失去,亦或所得!生活的节奏,常常让我们带着急急忙忙的节奏去追赶,也许这并不是每个人所期望的生活方式!于他人,于自己 ...

  4. 20151024_004_C#基础知识(C#中的访问修饰符,继承,new关键字,里氏转换,is 和 as,多态,序列化与反序列化)

    1:C#中的访问修饰符 public: 公共成员,完全公开,没有访问限制. private: 私有的,只能在当前类的内部访问. protected: 受保护的,只能在当前类的内部以及该类的子类中访问. ...

  5. C# 基础(一) 访问修饰符、ref与out、标志枚举等等

    C# 基础(一) 访问修饰符.ref与out.标志枚举等等 一.访问修饰符 在C#中的访问修饰符有:private.protected.internal.public public:公共类型,同一程序 ...

  6. Java基础——protected访问修饰符探讨

    Java基础——protected访问修饰符探讨 根据官方说法:(如图) protected修饰符是可以修饰其他包中的子孙类的,但是我做了个实验,结果发现了一个有趣的现象! 具体请往下看: packa ...

  7. C#基础知识八之访问修饰符

    1.  类的访问修饰符 修饰符 访问权限 无或者internal 只能在同一个程序集中访问类 public 同一个程序集或引用该程序集的外部都可访问类 abstract或internal abstra ...

  8. .NET 基础 一步步 一幕幕 [注释、命名规则、访问修饰符、数据类型、常量、变量]

    注释.命名规则.访问修饰符.数据类型.常量.变量 话说一个不会写注释的程序猿的不是一个好吃货,我们本篇就从注释开始说起好了. 在C#中有三种注释: 第一种:单行注释  以//开头,后面的就是注释内容 ...

  9. JAVA_SE基础——59.权限访问修饰符

    了解了包的概念,就可以系统的介绍Java中的访问控制级别.在Java中,针对类.成员方法和属性提供了四种访问级别,分别是private.default.protected和public. 权限访问修饰 ...

随机推荐

  1. Scrapy使用详细记录

    这几天,又用到了scrapy框架写爬虫,感觉忘得差不多了,虽然保存了书签,但有些东西,还是多写写才好啊 首先,官方而经典的的开发手册那是需要的: https://doc.scrapy.org/en/l ...

  2. js apply()、call() 使用参考

    引入,求一个数组的最大值,有这么一种快捷方法:Math.max.apply(null,arr); 但是最初看 JavaScript高级程序设计 的时候,没看懂,原文(斜体表示)如下: 每个函数都包含两 ...

  3. rabbitMq延时消息分级别

    做支付平台的时候.需要实现接受上游支付消息,通知给下游渠道. 针对下游渠道:要实现 按通知次数 递进 延时通知 下游渠道的支付/签约/代扣的状态 可参考微信按照 15/15/30/180/1800/1 ...

  4. Spring中的事物管理----HelloWorld

    在学习Spring的事物管理之前明白先明白几个概念1什么是事物:事务就是一系列的动作, 它们被当做一个单独的工作单元. 这些动作要么全部完成, 要么全部不起作用例子说明:例如银行转账,A账户转账(转2 ...

  5. PAT 甲级 1025 PAT Ranking

    1025. PAT Ranking (25) 时间限制 200 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue Programmi ...

  6. 剑指Offer——把二叉树打印成多行

    题目描述: 从上到下按层打印二叉树,同一层结点从左至右输出.每一层输出一行. 分析: 二叉树的层次遍历,利用队列. 代码: /* struct TreeNode { int val; struct T ...

  7. VC++SDK编程——字体及位置示例

    #include <Windows.h> #include <tchar.h> #include <math.h> #define PI 3.1415926 BOO ...

  8. linux页缓存

    2017-04-25 本节就聊聊页缓存这个东西…… 一.概述 页缓存是一个相对独立的概念,其根本目的是为了加速对后端设备的IO效率,比如文件的读写.页缓存顾名思义是以页为单位的,目前我能想到的在两个地 ...

  9. spring MVC中的异常统一处理

    1.spring MVC中定义了一个标准的异常处理类SimpleMappingExceptionResolver 该类实现了接口HandlerExceptionResolver 2.看下SimpleM ...

  10. maven仓库配置

    apache官方提供的maven库下载速度比较慢,所以可以配置成aliyun的maven库,这样在构建项目的时候速度会提升很多,具体方法如下: vim /usr/local/maven/conf/se ...