[.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:\KiteSource\Temp\PageLoadAndOnload\ParentAndSon\MAA.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:\KiteSource\Temp\PageLoadAndOnload\ParentAndSon\MAA.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:\KiteSource\Temp\PageLoadAndOnload\ParentAndSon\MAA.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)

posted on 2014-03-12 16:55  风筝blog  阅读(378)  评论(0编辑  收藏  举报