首页 > 代码库 > 第七章 继承和多态

第七章 继承和多态

1 继承

1.1 基类与派生类

C#中的类不支持多继承。只有在类和接口之间可以实现多继承。

        public static void Main()        {            Business c1 = new Business();            c1.Name = "李明";            c1["办公电话"] = "07188888888";            c1.Output();            ClassMate c2 = new ClassMate();            c2.Name = "张鹏";            c2.Birthday = new DateTime(1978, 12, 31);            c2.Output();        }
    /// <summary>    /// 基类:联系人Contact    /// </summary>    public class Contact    {        //字段        protected string m_name;        protected string m_homePhone = "未知";        protected string m_busiPhone = "未知";        protected string m_mobilePhone = "未知";        //属性        public string Name        {            get            {                return m_name;            }            set            {                m_name = value;            }        }        //索引函数        public string this[string sType]        {            get            {                string type = sType.ToUpper();                switch (type)                {                    case "住宅电话":                        return m_homePhone;                    case "办公电话":                        return m_busiPhone;                    case "手机":                        return m_mobilePhone;                    default:                        return null;                }            }            set            {                string type = sType.ToUpper();                switch (type)                {                    case "住宅电话":                        m_homePhone = value;                        break;                    case "办公电话":                        m_busiPhone = value;                        break;                    case "手机":                        m_mobilePhone = value;                        break;                    default:                        throw new ArgumentOutOfRangeException();                }            }        }        //构造函数        public Contact()        {        }        //方法        public void Output()        {            Console.WriteLine("姓名:{0}", m_name);            Console.WriteLine("住宅电话:{0}", m_homePhone);            Console.WriteLine("办公电话:{0}", m_busiPhone);            Console.WriteLine("手机:{0}", m_mobilePhone);            Console.WriteLine();        }    }
    /// <summary>    /// 派生类:商务Business    /// </summary>    public class Business:Contact    {        //字段        protected string m_busiFax = "未知";        protected string m_title = "先生/女士";        //属性        public string Title        {            get            {                return m_title;            }            set            {                m_title = value;            }        }    }
    /// <summary>    /// 派生类:同学ClassMate    /// </summary>    public class ClassMate:Contact    {        //字段        protected DateTime m_birthday;        //属性        public DateTime Birthday        {            get            {                return m_birthday;            }            set            {                m_birthday = value;            }        }    }

1.2 隐藏基类的成员

通过new关键字来隐藏基类中的成员,来存储不同的信息或执行不同的操作。

new关键字放在访问限制修饰符的前后均可,但一定要在成员的类型说明之间

隐藏基类成员时所使用的new关键字属于一种修饰符,与创建对象的new操作符是完全不同的。

1.3 base关键字

this关键字可以用来访问当前对象,而base关键字则可以用来访问基类对象,调用基类对象的成员。

//方法public new void Output(){    base.Output();    Console.WriteLine("...");}

1.4 继承中的构造函数和析构函数

创建一个派生类的实例,在执行其构造函数代码之前,会隐式的调用基类的构造函数。

析构函数的调用顺序相反,首先调用当前对象的析构函数,依次调用各级基灶的析构函数。

对于不带参数的默认构造函数,如果基类中已经有了定义,派生类可以隐式的继承。一旦基类中定义了带参数的构造函数,派生类的继承就不是隐式的了,而是要提供参数数量和类型都是基类构造函数相同的构造函数。例如基类Contact中定义了下面的构造函数:

public Contact(string sName){    m_name=sName;}

那么下面的代码是错误的:

Business c1= new Business("李四");Classmate c2= new Classmate("张鹏");

下面是一个完整的示例:

    public class NewInheritSample    {        static void Main()        {            //Business c2 = new Business();错误的代码            Business c1 = new Business("李明");            c1["办公电话"] = "01088888888";            c1["商务传真"] = "01066666666";            c1.Output();            ClassMate c2 = new ClassMate("张鹏");            c2.Birthday = new DateTime(1977, 02, 19);            c2.Output();        }    }
    /// <summary>    /// 基类:联系人Contact    /// </summary>    public class Contact    {        //字段        protected string m_name;        protected string m_homePhone = "未知";        protected string m_busiPhone = "未知";        protected string m_mobilePhone = "未知";        //属性        public string Name        {            get            {                return m_name;            }            set            {                m_name = value;            }        }        //索引函数        public string this[string sType]        {            get            {                string type = sType.ToUpper();                switch (type)                {                    case "住宅电话":                        return m_homePhone;                    case "办公电话":                        return m_busiPhone;                    case "手机":                        return m_mobilePhone;                    default:                        return null;                }            }            set            {                string type = sType.ToUpper();                switch (type)                {                    case "住宅电话":                        m_homePhone = value;                        break;                    case "办公电话":                        m_busiPhone = value;                        break;                    case "手机":                        m_mobilePhone = value;                        break;                    default:                        throw new ArgumentOutOfRangeException();                }            }        }        //构造函数        public Contact()        {        }        public Contact(string sName)        {            m_name = sName;        }        //方法        public void Output()        {            Console.WriteLine("姓名:{0}", m_name);            Console.WriteLine("住宅电话:{0}", m_homePhone);            Console.WriteLine("办公电话:{0}", m_busiPhone);            Console.WriteLine("手机:{0}", m_mobilePhone);            Console.WriteLine();        }    }    /// <summary>    /// 派生类:商务Business    /// </summary>    public class Business:Contact    {        //字段        protected string m_busiFax = "未知";        protected string m_title = "先生/女士";        //属性        public string Title        {            get            {                return m_title;            }            set            {                m_title = value;            }        }        //索引函数        public new string this[string sType]        {            get            {                string type=sType.ToUpper();                switch(type)                {                    case "商务传真":                        return m_busiFax;                    default:                        return base[sType];                }            }            set            {                string type = sType.ToUpper();                switch (type)                {                    case "商务传真":                        m_busiFax = value;                        break;                    default:                        base[sType] = value;                        break;                }            }        }        //构造函数        public Business(string sName)            : base(sName)        {        }        //方法        public new void Output()        {            base.Output();            Console.WriteLine("商务传真:{0}", m_busiFax);            Console.WriteLine();        }    }    /// <summary>    /// 派生类:同学ClassMate    /// </summary>    public class ClassMate:Contact    {        //字段        protected DateTime m_birthday;        //属性        public DateTime Birthday        {            get            {                return m_birthday;            }            set            {                m_birthday = value;            }        }        //构造函数        public ClassMate(string sName)            : base(sName)        {        }        //方法        public new void Output()        {            base.Output();            Console.WriteLine("生日:{0}", m_birthday.ToString());        }    }

 

2 多态性

2.1 虚拟方法和重载方法

派生类很少一成不变的去继承基类中的所有成员。一种情况是:派生类中的方法成员隐藏基类中同名的方法成员,通过new关键字对成员修饰。另一种更普遍和灵活的情况是:将基类的方法成员定义为虚拟方法,而在派生类中对虚拟方法进行重载。后者的优势在于它可以实现运行时的多态性。

基类的虚拟方法通过关键字virtual进行定义。下面是一个完整的例子:

    class VirtualInheritSample    {        static void Main(string[] args)        {            Business c1 = new Business("李明");            c1["办公电话"] = "01088888888";            c1["商务传真"] = "01066666666";            ClassMate c2 = new ClassMate("张鹏");            c2.Birthday = new DateTime(1977, 02, 19);            Contact c = c1;            c.Output();//for Business            c = c2;            c.Output();//for Classmate        }    }    /// <summary>    /// 基类:联系人Contact    /// </summary>    public class Contact    {        //字段        protected string m_name;        protected string m_homePhone = "未知";        protected string m_busiPhone = "未知";        protected string m_mobilePhone = "未知";        //属性        public string Name        {            get            {                return m_name;            }            set            {                m_name = value;            }        }        //虚拟索引函数        public virtual string this[string sType]        {            get            {                string type = sType.ToUpper();                switch (type)                {                    case "住宅电话":                        return m_homePhone;                    case "办公电话":                        return m_busiPhone;                    case "手机":                        return m_mobilePhone;                    default:                        return null;                }            }            set            {                string type = sType.ToUpper();                switch (type)                {                    case "住宅电话":                        m_homePhone = value;                        break;                    case "办公电话":                        m_busiPhone = value;                        break;                    case "手机":                        m_mobilePhone = value;                        break;                    default:                        throw new ArgumentOutOfRangeException();                }            }        }        //构造函数        public Contact()        {        }        public Contact(string sName)        {            m_name = sName;        }        //虚拟方法        public virtual void Output()        {            Console.WriteLine("姓名:{0}", m_name);            Console.WriteLine("住宅电话:{0}", m_homePhone);            Console.WriteLine("办公电话:{0}", m_busiPhone);            Console.WriteLine("手机:{0}", m_mobilePhone);            Console.WriteLine();        }    }    /// <summary>    /// 派生类:商务Business    /// </summary>    public class Business:Contact    {        //字段        protected string m_busiFax = "未知";        protected string m_title = "先生/女士";        //属性        public string Title        {            get            {                return m_title;            }            set            {                m_title = value;            }        }        //重载索引函数        public override string this[string sType]        {            get            {                string type=sType.ToUpper();                switch(type)                {                    case "商务传真":                        return m_busiFax;                    default:                        return base[sType];                }            }            set            {                string type = sType.ToUpper();                switch (type)                {                    case "商务传真":                        m_busiFax = value;                        break;                    default:                        base[sType] = value;                        break;                }            }        }        //构造函数        public Business(string sName)            : base(sName)        {        }        //重载方法        public override void Output()        {            base.Output();            Console.WriteLine("商务传真:{0}", m_busiFax);            Console.WriteLine();        }    }    /// <summary>    /// 派生类:同学ClassMate    /// </summary>    public class ClassMate:Contact    {        //字段        protected DateTime m_birthday;        //属性        public DateTime Birthday        {            get            {                return m_birthday;            }            set            {                m_birthday = value;            }        }        //构造函数        public ClassMate(string sName)            : base(sName)        {        }        //重载方法        public override void Output()        {            base.Output();            Console.WriteLine("生日:{0}", m_birthday.ToString());        }    }
View Code

 提示:

--如果派生类中使用override关键字定义了重载方法,那么也就允许该类自己的派生类继续重载这个方法,因此重载方法也默认是一种虚拟方法,但不能同时使用virtual和override修饰一个方法。

--虚拟方法可以在派生类中重载,因此虚拟方法不能是私有的

--在基类和派生类中,对同一个虚拟方法和重载方法的访问限制应当相同,要么都使用public,要么都使用protected。

2.2 抽象类和抽象方法

第七章 继承和多态