要点:

  • 基类和派生类
  • 防止类被实例化
  • 构造函数,尤其是引用基类的构造函数
  • 静态方法的新发现
  • 相关代码下载

缘由:

经过最近几天的反复思考,今天终于决定,把用户和用户有关的功能从xpnewPage类(这个类是我用来继承System.Web.UI.Page类并派生到后台admin和前台所有.aspx页面的的基类)中分离出来。分离的原因有两个:一方面,是我发觉,放在xpnewPage中用起来不方便,曾经想过单独放到静态类里面,不过很犹豫;另外就是有一次拿我做的用户验证和asp.net 2.0 提供的MemberShip做比较时受到启发,在dot net里面也是分离每次使用都用实例化的。

所以我就下定决心,把用户的功能,从xpnewPage中分离出来。

分离之后,我继续使用基类:前台派生类+后台派生类的模式。

正文:

一、基类和派生类

目前后台的功能基本已经成形了,所以主要是运用在前台用户,后台用户得以后有空的时候再说了。所以,基类是xpnew.User,派生类是xpnew.FrontUser。

在这里面,我准备把前台用户和后台用户的通用的功能,集中起来,放到xpnew.User类中。前台用户的特性放在xpnew.FrontUser类中。比如说在xpnew.User没有限定CookieName的值,但是在xpnew.FrontUser中必须指定CookieName的值。

所以对这种情况,如果从基类和派生类的技术出发那么就应该在派生类中通过重写属性来实现。下面是简略的代码:

namespace xpnew
{
    public class User
    {
        private string _CookieName;
        public User()        {        }
        public virtual string CookieName
        {
            get
            {
                return _CookieName;
            }
            set
            {
                _CookieName = value;
            }
        }
    }
    public class FrontUser:User{
        public override string CookieName
        {
            get
            {
                base.CookieName = getCookieName();
                return base.CookieName;
            }
            set
            {
                base.CookieName = value;
            }
        }
        private string getCookieName()
        {
            string result;
            result = "UserCookies";//实际的功能比这个复杂,这里只做简单的表示。
            return result;
        }
    }
}

这里面分别在基类和派生类使用了virtual和override关健字,如果基类没有使用virtural关健字,那么派生类就要使用new关键字来强调,否则vs的编译的时候会给出提示。

二、防止类被实例化

类的实例化,就是以类为模板在内存生成一个具体的对象。例如:

User u = new User();

在这里面User类是前台后台所有用户功能的抽象,虽然它本身可以实现一些功能,但是,功能并不完整,所以有必要防止这个类被实例化。

今天翻看了一下MSDN,总结出来两种不能实例化的情况:

2.1 抽象类和静态类

抽象类是在类前面加上abstract关键字,抽象类的成员全部(或者部分,这个具体的差别我还没来得及实验总结,两个星期以前研究了一下virtual类,好象vrtual类的成员必须全部都是vitural的,抽象类是不是全部都得是抽象的,我记不清没有没实验过了)是抽象的,没有代码实现的,所以这样的类是无法实例化的,假如实例化的话,编译器肯定是无法处理的,所以抽象类是不能实例化的。

静态类是在类前面加上static,静态类的成员全部是静态的,静态类和和静态的方法不需要实例化就能使用。所以静态类也是不能实例化的。

2.2 私有构造函数

根据MSDN所说,我的理解,就是静态类的构造函数被私有化(private)了。同样的情况是,对非静态的类,私有化构造函数之后,这样的类也一样是不能实例化的。

例如,在这里把public User(){} 换成 private User(){},那么就能使用xpnew.User  u =  new xpnew.User();了。因为在C#中 private关键字限定只能在类内部访问,只能是User.a访问User.b这样。现在跑到类的外面,就是不允许的。

但是,在当前的情况下private User(){},也限定了FrontUser的访问,基类的private成员连派生类也不能访问,就好像说爸爸有个盒子,连儿子也不能动,不知道里面有什么东西。程序运行的时候,提示:“xpnew.User.User()”不可访问,因为它受保护级别限制。

namespace xpnew
{
    public class User
    {
        private User()
        {        }
    }
    public class FrontUser:User
    {
        public FrontUser()
        {        }
    }
}

C#的原理是,每个例在实例化的时候,会运行构造函数,而且一个类的构造函数被调用的时候,也会自动调用基类的构造函数,上面的代码和下面是等效的:

public FrontUser():Base(){   }

实际运行的过程也是先运行User()再运行FrontUser()。虽然在代码上没有表现出来,但是C#内在的运行机制却会自动完成这个步骤。

对于上面的情况解决办法是更换private为protected,

Code
namespace xpnew
{
    public class User
    {
        protected User()  { }
    }
    public class FrontUser:User
    {
        public FrontUser()  {    }
    }
}

三、构造函数,除了默认的构造函数之外

上面已经提到了一部分构造函数的内容。下面说一说其它几种情况。

3.1 创建对象的时候一定要用构造函数么?

答案是否定的。有的对象不能使用构造函数,或者有类本身没有构造函数,所以,有的对象创建的过程中必须是通过其它的类、对象、方法创建的。这方面的例子,以后我再慢慢收集整理。

还有时候,获取对象有很多种办法,不必非得使用构造函数。例如下面:

HttpCookie yourcookie = new HttpCookie();

HttpCookie mycookie = HttpContent.Current.Request.Cookies["UserName"];

3.2 构造函数的多样性(暂用这个词)

一类可以有多个重载的构造函数,也可以灵活多样的继承基类的构选函数,下面的代码给出了一部分情况:

Code
    public class User
    {
        private string _CookieName;
        public string CookieName
        {
            get { return _CookieName; }
            set { _CookieName = value; }
        }
        protected User()
        {
        }
        protected User(string cookiename)
        {
            CookieName = cookiename;
        }
    }
    public class FrontUser:User
    {
        
        /*第一种默认的继承
         public FrontUser(){}
         
         */
        /*第二种
        public FrontUser():base("UserCookie")
        {
        }
         */
        /*第三种
        public FrontUser()
        {        }
        public FrontUser(string cookiename) : base(cookiename) { }
         */
        /*第四种 这一种,是我目前采用的办法。
        public FrontUser() : this("UserCookie") { }
        public FrontUser(string cookiename) : base(cookiename) { }
        */
    }

第二种是最接我开始时构想的做法,印象中我最初学习C#的书本上有类似的用法。但是调试不成功,改来改去,变成了第四种的样子。以后有机会翻翻书再研究出一种最完美的形式吧。

四、静态方法的新发现

其实我原始的想法是这样的:

public FrontUser() : base(getUserCookie()){}

其中getUserCookie()(稍后有这个代码的最终版本),是通过web.config获取一个cookies的名称。

总体上而言,就是User类里没有具体的cookies检查,因为User类都不知道cookies的名称,怎么能检查呢?要检查的话,也得先设置CookieName属性才行。到了FrontUser类这里,在实例化的时候,就先指定CookieName,一气呵成。然后就能做在线检查、cookie合法检查等操作了。

但是这样的代码却是行不通的。提示的意思说getUserCookie()需要实例化才能使用。可是在构造函数这个地方,连FrontUser()都没有运行(基类的构造函数运行),哪还有它的机会?但是提示中也提到,出现这种情况的原因是这个getUserCookie()不是静态的方法, 所以解决的办法,就是给getUserCookie()加上static关键字。

    public class User
    {
        private string _CookieName;
        public string CookieName
        {
            get { return _CookieName; }
            set { _CookieName = value; }
        }
        protected User()
        {
        }
        protected User(string cookiename)
        {
            CookieName = cookiename;
        }
    }
    public class FrontUser:User
    {
        public FrontUser() : this(getCookieName()) {   }
        public FrontUser(string cookiename) : base(cookiename) { }

public static string getCookieName(){
            //实际代码比较复杂,这里用简略的方式给出
            return  "UserCookie";
        }
    }

后记:

  做到这里,就完全实现了通过重载构造函数,初始化派生类这样很拐弯的想法。最初的设想,总算是实现了。于是就上来写一篇博客。可是我却高兴不起来,我感觉样的代码有点别扭。尤其是FrontUser这是一个需要实例化的类,里面却使用了一个静态的方法。而且,我在写这篇博客的时候发现,其实还不如直接使用最简单的方式使用构造函数,然后设置User.CookieName属性了:

    public class User
    {
        private string _CookieName;
        public string CookieName
        {
            get { return _CookieName; }
            set { _CookieName = value; }
        }
        protected User()
        {
        }
    }
    public class FrontUser:User
    {
        public FrontUser()
        {
            CookieName = getCookieName();
        }
        public string getCookieName(){
            //实际代码比较复杂,这里用简略的方式给出
            return  "UserCookie";
        }
    }

想想这样七扭八歪的,最终回到了一个简单的办法上,有点可笑,收获就是复习了一些书本上的基本知识了。

另外,我在后面,把相关的三个文件传上来,里面还有一个文本文件的说明。

http://files.cnblogs.com/xpnew/test_code.rar

转载于:https://www.cnblogs.com/xpnew/archive/2008/12/09/1350564.html

复习:关于类的继承和构造函数相关推荐

  1. JS原型继承和类式继承

    类式继承(构造函数) JS中其实是没有类的概念的,所谓的类也是模拟出来的.特别是当我们是用new 关键字的时候,就使得"类"的概念就越像其他语言中的类了.类式继承是在函数对象内调用 ...

  2. C++ Primer 5th笔记(chap 15 OOP)继承的构造函数容器

    1. 继承的构造函数 1.1 C++11新标准中,派生类可以重用其直接基类定义的构造函数. 继承方式是提供一条注明了直接基类名的using声明语句. class Bulk_quote : public ...

  3. c++复习日记1 类的继承与派生

    8月16日,回顾一下c++继承与派生的知识. 继承是面向对象程序设计中软件重用的关键技术.类与类间的关系主要分has-a.uses-a.is-a三种,其中is-a有传递性,此种机制即为继承. 派生类对 ...

  4. 实现父类一个动物的类, 包括成员变量名字年龄皮毛颜色,带参数构造函数,动物类有一个方法,move,打印动物是可以动的 1.《实现一个子类老鼠的类,继承动物类,老鼠类继承父类成员变量,老鼠还有个自己的属

    编写一个程序,程序包括如下内容 实现父类一个动物的类, 包括成员变量名字年龄皮毛颜色,带参数构造函数,动物类有一个方法,move,打印动物是可以动的 1.<实现一个子类老鼠的类,继承动物类,老鼠 ...

  5. 从零开始学C++之继承(二):继承与构造函数、派生类到基类的转换

    一.不能自动继承的成员函数 构造函数(包括拷贝构造函数) 析构函数 =运算符 二.继承与构造函数 基类的构造函数不被继承,派生类中需要声明自己的构造函数. 声明构造函数时,只需要对本类中新增成员进行初 ...

  6. C++ 类继承:构造函数与析构函数调用顺序,派生类和基类之间的特殊关系,公有继承及其他

    文章目录 一.派生类构造函数与基类构造函数 二.创建与销毁派生类对象时,构造函数和析构函数的调用 三.派生类和基类之间的特殊关系 四.公有继承 (一).何为公有继承 (二).多态公有继承 (三).虚函 ...

  7. 虚继承,虚基类以及虚继承的构造函数

    目录 一.什么是虚继承,虚基类 二.定义虚继承的基本格式 三.虚继承的构造函数 一.什么是虚继承,虚基类 虚继承:在继承定义中包含了virtual关键字的继承关系 虚基类:在虚继承体系中的通过virt ...

  8. 6.12C++:继承基类的构造函数、单继承的构造函数、多继承的构造函数、派生类复制构造函数、派生类的析构函数

    1 继承基类的构造函数 class A{public:A(){}; // A的构造函数 }; class B : public A{public:using A:A: } 2 单继承的构造函数 cla ...

  9. C++类继承时构造函数与析构函数的执行顺序

    C++类继承时构造函数与析构函数的执行顺序 在C++类中,类A继承类B时,如果创建一个A的对象时,会首先调用基类的构造函数,再调用派生类的构造函数,而析构函数的执行相反,但是当基类和派生类分别有一个成 ...

  10. java的继承属于哪种类型_根据Java的继承原则,如果类B继承自类A,()。_学小易找答案...

    [单选题]关于FileOutputStream的说法错误的是?( ) [单选题]在教学过程中,控制( )大小.上下.左右或任意方向进行遮盖或显示,非常适合递进式观察.(3.3分) [单选题]交互式电子 ...

最新文章

  1. php中的isset函数,PHP函数isset()只能用于变量
  2. echarts图表的内边距_echarts——各个配置项详细说明总结
  3. java kotlin lateinit_15. Kotlin 究竟该不该用 lateinit?
  4. Google+强推实名制引爆不满 用户增速放缓
  5. Polyfill工作笔记001---简介
  6. 方维分享系统修改,本地安装失败,后台无法登陆
  7. ORA-01034: ORACLE not available ORA-27101: shared memory realm does not exist的原因分析
  8. Fragstats运行内存不够或卡顿问题解决
  9. 计算机二进制中的原码,反码,补码
  10. SM2证书的鉴定方法
  11. ARM9开发之学习过程总结
  12. 7.Flink实时项目之独立访客开发
  13. xml与json格式互转
  14. C++ 覆盖方法与重载方法
  15. 教你实现一个简单的对象深拷贝
  16. 模拟电路36(理想运算放大器——积分电路、微分电路4)
  17. 不平等博弈_不平等与全球性大流行:完美的风暴?
  18. 计算机专业学生宿舍用台式,大学带台式机的人多吗 方便吗
  19. 计算机网络个人简历优秀范文,计算机网络个人简历范文
  20. USB驱动始终不能成功下载安装

热门文章

  1. JDK9 为何要将 String 的底层实现由 char[] 改成了 byte[] ?
  2. 女程序员做了个梦,神评论。。。
  3. 推荐一个准确率99.9%的离线IP地址定位服务!
  4. 哀悼日网站全站变灰代码,最简单的还是ng这种方式...
  5. BAT都不让多表 join?这是为什么?
  6. 甲骨文裁员后续:近万招聘者哄抢甲骨文前员工
  7. 分布式MySQL集群方案,看看京东是怎么做的
  8. [转]MySQL修改root密码的多种方法
  9. 用R语言实现对不平衡数据的四种处理方法
  10. js判断IE浏览器及版本