• [.net基础]访问修饰符


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

    一、前言

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

    二、方法访问修饰符Internal

      (1)、创建工程ParentAndSon

      (2)、添加类ModelA

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

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

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

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

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

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

      可看出,只有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();
            }
        }
    }
    View Code

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

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

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

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

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

      可看出,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");
            }
        }
    }
    View Code

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

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

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

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

      (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();
            }
        }
    }
    View Code

      (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
    View Code

    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");
            }
        }
    }
    View Code

    MAAA:

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

    执行结果和【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");
            }
        }
    }
    View Code

    编译出错:

    Error    1    'ParentAndSon.MAA.InvokeShowProtected()': cannot override inherited member 'ParentAndSon.MA.InvokeShowProtected()' because it is not marked virtual, abstract, or override    D:KiteSourceTempPageLoadAndOnloadParentAndSonMAA.cs    10    30    ParentAndSon
    View Code

    所以不能改成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();
            }
        }
    }
    View Code

      (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();
            }
        }
    }
    View Code

      (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();
            }
        }
    }
    View Code

      (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();
            }
        }
    }
    View Code

      (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
    View Code

    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();
            }
        }
    }
    View Code

    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();
            }
        }
    }
    View Code

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

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

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

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

    编译不通过,提示:

    Error    6    'ParentAndSon.MAA.InvokeShowProtectedInternal()': cannot override inherited member 'ParentAndSon.MA.InvokeShowProtectedInternal()' because it is not marked virtual, abstract, or override    D:KiteSourceTempPageLoadAndOnloadParentAndSonMAA.cs    25    30    ParentAndSon
    View Code

    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");
            }
        }
    View Code

      (3)、添加子类MAA

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

      (4)、添加子类MAAA

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

      (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();
            }
    View Code

      (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
    View Code

    B、子类方法改用new

    MA不变,MAA如下:

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

    MAAA如下:

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

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

    C、子类方法改用override

    MA不变,MAA如下:

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

     MAAA如下:

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

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

    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
    View Code

    测试结果表明:

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

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

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

     参考:

    C#中 protected internal 和 internal 的区别  

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

    4、注意点

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

    父类:

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

    子类:

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

    编译报错:

    Error    2    'ParentAndSon.MAA.InvokeShowProtected()': cannot change access modifiers when overriding 'protected' inherited member 'ParentAndSon.MA.InvokeShowProtected()'    D:KiteSourceTempPageLoadAndOnloadParentAndSonMAA.cs    10    30    ParentAndSon
    View Code

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

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

    子类:

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

    孙类:

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

    可以正常调用。

    参考:

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

    (2014-03-12 18:22)

  • 相关阅读:
    Picture
    wolf and rabbit
    十进制转换为二进制(一直不会算的)
    各种排序
    折线分割平面
    字母数
    1001
    Primes
    大数的减法神秘数
    转: Windows Internet WinINet 学习笔记(2)
  • 原文地址:https://www.cnblogs.com/fiteg/p/3596701.html
Copyright © 2020-2023  润新知