深入浅出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关键字

  • 本文转自 powertoolsteam 51CTO博客,原文链接:http://blog.51cto.com/powertoolsteam/1643783,如需转载请自行联系原作者                                                                                                                

相关文章
【JavaSE专栏63】多态,父类引用子类的对象,面向对象编程中的重要概念
【JavaSE专栏63】多态,父类引用子类的对象,面向对象编程中的重要概念
|
3月前
|
Java 编译器
封装,继承,多态【Java面向对象知识回顾①】
本文回顾了Java面向对象编程的三大特性:封装、继承和多态。封装通过将数据和方法结合在类中并隐藏实现细节来保护对象状态,继承允许新类扩展现有类的功能,而多态则允许对象在不同情况下表现出不同的行为,这些特性共同提高了代码的复用性、扩展性和灵活性。
封装,继承,多态【Java面向对象知识回顾①】
|
6月前
|
C++
C++一分钟之-继承与多态概念
【6月更文挑战第21天】**C++的继承与多态概述:** - 继承允许类从基类复用代码,增强代码结构和重用性。 - 多态通过虚函数实现,使不同类对象能以同一类型处理。 - 关键点包括访问权限、构造/析构、菱形问题、虚函数与动态绑定。 - 示例代码展示如何创建派生类和调用虚函数。 - 注意构造函数初始化、空指针检查和避免切片问题。 - 应用这些概念能提升程序设计和维护效率。
45 2
|
5月前
|
Java
深入理解Java中的类与对象:封装、继承与多态
深入理解Java中的类与对象:封装、继承与多态
|
6月前
|
设计模式 存储 Java
JavaSE——面向对象高级二(2/4)-final关键字、常量、抽象类(认识抽象类、抽象类的好处、应用场景-模板方法设计模式)
JavaSE——面向对象高级二(2/4)-final关键字、常量、抽象类(认识抽象类、抽象类的好处、应用场景-模板方法设计模式)
33 0
|
设计模式 自然语言处理 C#
C#OOP之八 继承 接口和抽象类
C#OOP之八 继承 接口和抽象类
57 0
|
存储 数据安全/隐私保护 Python
面向对象编程(OOP):理解类、封装性的关键概念
面向对象编程(OOP):理解类、封装性的关键概念
156 0
|
编译器
面向对象编程的组合、多态、抽象类的基本介绍(二)
面向对象编程的组合、多态、抽象类的基本介绍
面向对象编程的组合、多态、抽象类的基本介绍(二)
|
Java 程序员 编译器
面向对象编程的组合、多态、抽象类的基本介绍(一)
面向对象编程的组合、多态、抽象类的基本介绍
面向对象编程的组合、多态、抽象类的基本介绍(一)
|
Python
【Python零基础入门篇 · 16】:类的继承(单继承和多继承)、继承重写、面向对象的多态、静态方法和类方法
【Python零基础入门篇 · 16】:类的继承(单继承和多继承)、继承重写、面向对象的多态、静态方法和类方法
205 0
【Python零基础入门篇 · 16】:类的继承(单继承和多继承)、继承重写、面向对象的多态、静态方法和类方法
下一篇
DataWorks