zoukankan      html  css  js  c++  java
  • 谈谈C#中的三个关键词new , virtual , override

        C#支持单继承,说到继承就不得不说new,virtual和override这三个关键词,灵活正确的使用这三个关键词,可以使程序结构更加清晰,代码重用性更高。

    以下是msdn中对new,virtual和override的定义:
            使用 new 修饰符显式隐藏从基类继承的成员。若要隐藏继承的成员,请使用相同名称在派生类中声明该成员,并用 new 修饰符修饰它。
            virtual 关键字用于修改方法或属性的声明,在这种情况下,方法或属性被称作虚拟成员。虚拟成员的实现可由派生类中的重写成员更改。
    调用虚方法时,将为重写成员检查该对象的运行时类型。将调用大部分派生类中的该重写成员,如果没有派生类重写该成员,则它可能是原始成员。默认情况下,方法是非虚拟的。不能重写非虚方法。
    不能将 virtual 修饰符与以下修饰符一起使用:
    static    abstract    override
            使用 override 修饰符来修改方法、属性、索引器或事件。重写方法提供从基类继承的成员的新实现。由重写声明重写的方法称为重写基方法。重写基方法必须与重写方法具有相同的签名。
    不能重写非虚方法或静态方法。重写基方法必须是虚拟的、抽象的或重写的。
    重写声明不能更改虚方法的可访问性。重写方法和虚方法必须具有相同的访问级修饰符。
    不能使用下列修饰符修改重写方法:
    new   static    virtual   abstract
    重写属性声明必须指定与继承属性完全相同的访问修饰符、类型和名称,并且重写属性必须是虚拟的、抽象的或重写的。 
     
    可以稍微归纳一下:
    1、对于基类中说明为虚的方法则必须在派生类中new或者override(:对于基类的虚方法,虽然你在派生类中即不new也不override,但系统还是会提示你添关键字。否则系统将视其为隐藏。我们的意思是一样的,但总觉得明明确确写上关键字还是好些)。
    2、如果用基类指针指向派生类对象的方式,动态匹配的源动力是virtual,而new和override都会阻止这种向下寻求匹配的行为,所以要使虚函数的性质得已保持下去,就要隐藏基类的虚方法,即在派生类中隐藏基类虚方法时,同时加以virtual关键字,使在多层次继承中能够调用到对象自身的版本。
    3、在多层次继承中,三个关键字使用次序有限定,new没有使用前提,即不管是普通方法、虚方法还是重写了的方法。virtual的使用,在它的基类不能有函数签名相同的方法,否则系统将提示添加new,即隐藏基类中的方法。virtual一般只出现一次,除非要在子类中隐藏父类的虚方法。override的使用是为了重写基类虚方法。
     
     
    还是我写AD的一个例子:
    Administrators页面中,需要根据用户是否在管理员这组中来判断用户是否可以进入页面
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    
    namespace ActiveDirectoryDemo.Pages
    {
        public partial class Administrators : AccessControl
        {
            protected new void Page_Load(object sender, EventArgs e)//有没有new都执行基类。。。我了个fuck,但是没有还会提示警告
            {
              //  base.IsUserIsAuthenticated();
                bool isUserNameInGroup = base.IsUserNameInGroup(User, "Administrators");
                if (isUserNameInGroup == false)
                {
                    string _userName = User.Identity.Name;
                    //用户没有权限,跳转回之前请求的页面,也可以在跳转页面不显示本页跳转的菜单
                    Response.Redirect(System.Web.Security.FormsAuthentication.GetRedirectUrl(_userName, false));
                }
    
            }
        }
    }
    AccessCOntrol中:
    
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    
    namespace ActiveDirectoryDemo.Pages
    {
        public class AccessControl : System.Web.UI.Page
        {
            protected virtual void Page_Load(object sender, EventArgs e)
            {
                if (!User.Identity.IsAuthenticated)
                {
                    Response.Redirect("GotoUrl.aspx?returnUrl=" + Server.UrlEncode("Login.aspx"));
                }
            }
            public void IsUserIsAuthenticated() 
            {
                if (!User.Identity.IsAuthenticated)
                {
                    Response.Redirect("GotoUrl.aspx?returnUrl=" + Server.UrlEncode("Login.aspx"));
                }
            }
            public bool IsUserNameInGroup(System.Security.Principal.IPrincipal user, string groupName)
            {
                LDAPAuthentication adAuth = new LDAPAuthentication();
                bool isUserNameInGroup = false;
                string _userName = user.Identity.Name;
                string[] _userNames = adAuth.GetUsersForGroup(groupName);
                for (int i = 0; i < _userNames.Length; i++)
                {
                    if (_userName == _userNames[i])
                    {
                        isUserNameInGroup = true;
                    }
                }
                return isUserNameInGroup;
            }
                
    
        }
    }
    
    
    
     

    如果 基类(老子) 中方法用virtual修饰了  

    无论 派生类(儿子)中的方法使用 new  与否 都不会影响结果:就是一定会执行 老子中的方法

    下面 基类中是去掉virtual关键字后:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    
    namespace ActiveDirectoryDemo.Pages
    {
        public class AccessControl : System.Web.UI.Page
        {
            protected  void Page_Load(object sender, EventArgs e)
            {
                if (!User.Identity.IsAuthenticated)
                {
                    Response.Redirect("GotoUrl.aspx?returnUrl=" + Server.UrlEncode("Login.aspx"));
                }
            }

    这次执行,派生类(儿子)中的Page_Load事件得到了执行

    但是基类(老子)中的Page_Load事件没有得到执行

    所以没有进行

    User.Identity.IsAuthenticated

    的校验,所以少了一个步骤;

    最终决定采用上一篇中的 方法进行更改,不使用virtual和new关键字,直接调用父类中的方法

    使用base关键字 

    总结:在基类使用了virtual情况下,派生类(儿子)的同一事件不会执行,除非使用override关键字。

    无论派生类中 有没有那个jb  new关键字


  • 相关阅读:
    hive报错 java.sql.SQLException: No suitable driver found for jdbc:hive://localhost:10000/default
    使用Beeline连接Hive
    hive报错 root is not allowed to impersonate root (state=08S01,code=0)
    hive报错 Could not open client transport with JDBC Uri: jdbc:hive2://node01:10000/default:java.net.ConnectException refused
    excel快速删除空值单元格,数据上移
    FineBI 图表选择
    数据库连接池大小设置?
    工作中有待留❤️积累的一些经验
    内存包括随机存储器(RAM),只读存储器(ROM),以及高速缓存(CACHE)。RAM最重要
    我自己ood的复习思路:抄
  • 原文地址:https://www.cnblogs.com/YoungPop-Chen/p/3341180.html
Copyright © 2011-2022 走看看