[.net基础]访问修饰符
标题:[.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 1 '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 10 30 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 6 '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 25 30 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 的区别
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 2 'ParentAndSon.MAA.InvokeShowProtected()': cannot change access modifiers when overriding 'protected' inherited member 'ParentAndSon.MA.InvokeShowProtected()' D:\KiteSource\Temp\PageLoadAndOnload\ParentAndSon\MAA.cs 10 30 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)