• 深入浅出OOP(四): 多态和继承(抽象类)


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

    Abstract Classes

    image

    在微软的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。

    image

    非抽象类的抽象函数

    我们再看看这些代码:

    /// <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#)

  • 相关阅读:
    线程同步之条件变量使用手记
    如何实现文件增量同步——算法
    javascript 复习笔记
    cocos2dx 多图层点击事件及管理相关问题记录
    cocos2dx 2.1.1 jsbinding 游戏帧数下降问题记录
    cocos2dx jsb + cocosbuilder 编译到安卓下问题处理(待续)
    cocos2dxjsb及Cocosbuilder使用相关问题处理记录
    cocos2dx jsb 的本地存储
    cocos2dxjsb 跨语言调用及第三方集成 过程记录
    cocos2dx 2.1.1 升级2.1.3版本 记录
  • 原文地址:https://www.cnblogs.com/powertoolsteam/p/Diving-in-OOP-Day-Polymorphism-and-Inheritance-All.html
Copyright © 2020-2023  润新知