zoukankan      html  css  js  c++  java
  • 深入理解OOP(四): 多态和继承(抽象类)

    在本文中,我们讨论OOP中的热点之一:抽象类。抽象类在各个编程语言中概念是一致的,但是C#稍微有些不一样。本文中我们会通过代码来实现抽象类,并一一进行解析。

     

    Abstract Classes

    在微软的MSDN中,对抽象类有如下的定义:

    用abstract 关键字可定义抽象类,要求其子类必须实现抽象类的函数、属性等。抽象类不可被实例化。抽象类提供了统一的定义,用于其不同子类直接共享数据、函数。 抽象类也可定义抽象函数。


    Abstract Classes实战

    在Visual Studio中添加Console程序,并命名为“InheritanceAndPolymorphism”,添加ClassA.cs,添加抽象类ClassA。

    using System;
    
    namespace InheritanceAndPolymorphism
    {
        public abstract class ClassA
        {
    
        }
    
        /// <summary>
        /// Program: used to execute the method.
        /// Contains Main method.
        /// </summary>
        public class Program
        {
            private static void Main(string[] args)
            {
                ClassA classA = new ClassA();
                Console.ReadKey();
            }
        }
    }

     编译报错:

    Compile time error: Cannot create an instance of the abstract class or interface 'InheritanceAndPolymorphism.ClassA'

    结论:无法用new关键字来实例化一个抽象类。


    Abstract Class的非抽象函数

    给抽象类ClassA添加一些非抽象函数的代码:

    /// <summary>
        /// Abstract class ClassA
        /// </summary>
        public abstract class ClassA
        {
            public int a;
            public void XXX()
            {
                
            }
        }
    
        /// <summary>
        /// Program: used to execute the method.
        /// Contains Main method.
        /// </summary>
        public class Program
        {
            private static void Main(string[] args)
            {
                ClassA classA = new ClassA();
                Console.ReadKey();
            }
        }

    编译,依然报错。 抽象类无论是否有抽象、非抽象函数,均无法通过new关键字来实例化。


    Abstract Class作为基类

    我们把抽象类作为基类,添加ClassB—使之继承自ClassA。

    /// <summary>
        /// Abstract class ClassA
        /// </summary>
        public abstract class ClassA
        {
            public int a;
            public void XXX()
            {
                
            }
        }
    
        /// <summary>
        /// Derived class.
        /// Class derived from abstract class ClassA
        /// </summary>
        public class ClassB:ClassA
        {
            
        }
    
        /// <summary>
        /// Program: used to execute the method.
        /// Contains Main method.
        /// </summary>
        public class Program
        {
            private static void Main(string[] args)
            {
                ClassB classB = new ClassB();
                Console.ReadKey();
            }
        }

    编译的结果:不再报错。

    结论:一个类可以继承自abstract 修饰的抽象类,且可被new关键字初始化。


    Abstract Class的非抽象函数声明

    在ClassA中声明YYY函数--无函数体。

    /// <summary>
        /// Abstract class ClassA
        /// </summary>
        public abstract class ClassA
        {
            public int a;
            public void XXX()
            {
                
            }
    
            public void YYY();
        }
    
        /// <summary>
        /// Derived class.
        /// Class derived from abstract class ClassA.
        /// </summary>
        public class ClassB:ClassA
        {
            
        }
    
        /// <summary>
        /// Program: used to execute the method.
        /// Contains Main method.
        /// </summary>
        public class Program
        {
            private static void Main(string[] args)
            {
                ClassB classB = new ClassB();
                Console.ReadKey();
            }
        }

    编译,结果报错:

    Compile time error: 'InheritanceAndPolymorphism.ClassA.YYY()' must declare a body because it is not marked abstract, extern, or partial

    结论是需要对YYY添加函数体,或者添加abstract的修饰符。


    Abstract Class的抽象函数声明

    在ClassA的YYY前,添加abstract修饰符。

    /// <summary>
        /// Abstract class ClassA
        /// </summary>
        public abstract class ClassA
        {
            public int a;
            public void XXX()
            {
                
            }
    
           abstract public void YYY();
        }
    
        /// <summary>
        /// Derived class.
        /// Class derived from abstract class ClassA.
        /// </summary>
        public class ClassB:ClassA
        {
            
        }
    
        /// <summary>
        /// Program: used to execute the method.
        /// Contains Main method.
        /// </summary>
        public class Program
        {
            private static void Main(string[] args)
            {
                ClassB classB = new ClassB();
                Console.ReadKey();
            }
        }

    编译结果,报错:

    Compiler error: 'InheritanceAndPolymorphism.ClassB' does not implement inherited abstract member 'InheritanceAndPolymorphism.ClassA.YYY()'

    结论:我们在abstract 类中声明了一个abstract 的函数,但是并未在其子类ClassB中实现其内容;当使用new关键字初始化ClassB的时候则会报错----无法使用new关键字初始化一个abstract类。


    子类继承实现抽象函数

    在子类中添加YYY的实现。

    /// <summary>
        /// Abstract class ClassA
        /// </summary>
        public abstract class ClassA
        {
            public int a;
            public void XXX()
            {
                
            }
    
           abstract public void YYY();
        }
    
        /// <summary>
        /// Derived class.
        /// Class derived from abstract class ClassA.
        /// </summary>
        public class ClassB:ClassA
        {
            public void YYY()
            {
                 
            }
        }
    
        /// <summary>
        /// Program: used to execute the method.
        /// Contains Main method.
        /// </summary>
        public class Program
        {
            private static void Main(string[] args)
            {
                ClassB classB = new ClassB();
                Console.ReadKey();
            }
        }

    编译结果,报错:

    Compile time error: 'InheritanceAndPolymorphism.ClassB' does not implement inherited abstract member 'InheritanceAndPolymorphism.ClassA.YYY()' Compile time warning: 'InheritanceAndPolymorphism.ClassB.YYY()' hides inherited member 'InheritanceAndPolymorphism.ClassA.YYY()'.

    结论:要使得子类继承基类的YYY函数,需要用到override关键字,然后才可以用new关键字实例化ClassB。


    非抽象类的抽象函数

    我们再看看这些代码:

    /// <summary>
        /// Abstract class ClassA
        /// </summary>
        public class ClassA
        {
            public int a;
            public void XXX()
            {
                
            }
    
           abstract public void YYY();
        }
    
        /// <summary>
        /// Derived class.
        /// Class derived from abstract class ClassA.
        /// </summary>
        public class ClassB:ClassA
        {
            public override void YYY()
            {
                 
            }
        }
    
        /// <summary>
        /// Program: used to execute the method.
        /// Contains Main method.
        /// </summary>
        public class Program
        {
            private static void Main(string[] args)
            {
                ClassB classB = new ClassB();
                Console.ReadKey();
            }
        }

    编译,结果报错:

    Compiler error: 'InheritanceAndPolymorphism.ClassA.YYY()' is abstract but it is contained in non-abstract class 'InheritanceAndPolymorphism.ClassA'

    结果分析:声明abstract的函数,必须同时声明类为abstract。abstract 的函数不能同时添加static或virtual关键字。


    抽象基类函数

    /// <summary>
        /// Abstract class ClassA
        /// </summary>
        public abstract class ClassA
        {
            public int a;
            public void XXX()
            {
                
            }
    
           abstract public void YYY();
        }
    
        /// <summary>
        /// Derived class.
        /// Class derived from abstract class ClassA.
        /// </summary>
        public class ClassB:ClassA
        {
            public override void YYY()
            {
                 base.YYY();
            }
        }
    
        /// <summary>
        /// Program: used to execute the method.
        /// Contains Main method.
        /// </summary>
        public class Program
        {
            private static void Main(string[] args)
            {
                ClassB classB = new ClassB();
                Console.ReadKey();
            }
        }

     编译,结果报错:

    Compile time error : Cannot call an abstract base member: 'InheritanceAndPolymorphism.ClassA.YYY()'

    结果分析:ClassB中无法使用base调用基类的abstract函数--因为其不存在。

    最后一个问题,可否在抽象类中添加sealed关键字,结果是不可以。

    抽象类不能添加sealed、static类修饰符的。


    结论

    通过下面几点,归纳一下本文的结论。

    • 无法使用new来实例化abstract 抽象类
    • abstract 抽象类可以有子类,其子类实现抽象方法后,可被new实例化对象
    • 如声明了abstract 的函数,则必须声明abstract 的类
    • 当override抽象基类,无法修改基类函数的签名
    • abstract函数,无法同时添加static、virtual关键字
    • abstract 类无法被声明为sealed、static类

    原文链接:Diving in OOP (Day 4): Polymorphism and Inheritance (All About Abstract Classes in C#)

    译文链接:http://www.cnblogs.com/powertoolsteam/p/Diving-in-OOP-Day-Polymorphism-and-Inheritance-All.html

  • 相关阅读:
    【Java EE 学习 81】【CXF框架】【CXF整合Spring】
    【Java EE 学习 80 下】【调用WebService服务的四种方式】【WebService中的注解】
    【Java EE 学习 80 上】【WebService】
    【Java EE 学习 79 下】【动态SQL】【mybatis和spring的整合】
    【Java EE 学习 79 上】【mybatis 基本使用方法】
    【Java EE 学习 78 下】【数据采集系统第十天】【数据采集系统完成】
    【Java EE 学习 78 中】【数据采集系统第十天】【Spring远程调用】
    【Java EE 学习 78 上】【数据采集系统第十天】【Service使用Spring缓存模块】
    【Java EE 学习 77 下】【数据采集系统第九天】【使用spring实现答案水平分库】【未解决问题:分库查询问题】
    【Java EE 学习 77 上】【数据采集系统第九天】【通过AOP实现日志管理】【通过Spring石英调度动态生成日志表】【日志分表和查询】
  • 原文地址:https://www.cnblogs.com/xijianyao/p/5122457.html
Copyright © 2011-2022 走看看