在本文中,我们讨论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#)

深入浅出OOP(四): 多态和继承(抽象类)的更多相关文章

  1. 深入理解OOP(四): 多态和继承(抽象类)

    在本文中,我们讨论OOP中的热点之一:抽象类.抽象类在各个编程语言中概念是一致的,但是C#稍微有些不一样.本文中我们会通过代码来实现抽象类,并一一进行解析. 深入理解OOP(一):多态和继承(初期绑定 ...

  2. 深入理解OOP(二):多态和继承(继承)

    本文是深入浅出OOP第二篇,主要说说继承的话题. 深入理解OOP(一):多态和继承(初期绑定和编译时多态) 深入理解OOP(二):多态和继承(继承) 深入理解OOP(三):多态和继承(动态绑定和运行时 ...

  3. 深入理解OOP(三):多态和继承(动态绑定和运行时多态)

    在前面的文章中,我们介绍了编译期多态.params关键字.实例化.base关键字等.本节我们来关注另外一种多态:运行时多态, 运行时多态也叫迟绑定. 深入理解OOP(一):多态和继承(初期绑定和编译时 ...

  4. 深入理解OOP(第一天):多态和继承(初期绑定和编译时多态)

    在本系列中,我们以CodeProject上比较火的OOP系列博客为主,进行OOP深入浅出展现. 无论作为软件设计的高手.或者菜鸟,对于架构设计而言,均需要多次重构.取舍,以有利于整个软件项目的健康构建 ...

  5. 深入浅出OOP(六): 理解C#的Enums

    MSDN定义:枚举类型(也称为枚举)为定义一组可以赋给变量的命名整数常量提供了一种有效的方法.  例如,假设您必须定义一个变量,该变量的值表示一周中的一天. 该变量只能存储七个有意义的值. 若要定义这 ...

  6. 深入浅出OOP(五): C#访问修饰符(Public/Private/Protected/Internal/Sealed/Constants)

    访问修饰符(或者叫访问控制符)是面向对象语言的特性之一,用于对类.类成员函数.类成员变量进行访问控制.同时,访问控制符也是语法保留关键字,用于封装组件. Public, Private, Protec ...

  7. 深入浅出OOP(二): 多态和继承(继承)

    本文是深入浅出OOP第二篇,主要说说继承的话题. 继承的介绍 在OOP中,继承有如下的定义: 继承是一种OOP的机制,用于派生继承预定义的类 在这个继承关系中,预定义的类是基类,新类是子类 继承常常用 ...

  8. python开发面向对象基础:接口类&抽象类&多态&钻石继承

    一,接口类 继承有两种用途: 一:继承基类的方法,并且做出自己的改变或者扩展(代码重用) 二:声明某个子类兼容于某基类,定义一个接口类Interface,接口类中定义了一些接口名(就是函数名)且并未实 ...

  9. OOP面向对象 三大特征 继承封装多态

    OOP面向对象 ----三大特征 继承封装多态 面向对象(Object Oriented,OO)是软件开发方法.面向对象的概念和应用已超越了程序设计和软件开发,扩展到如数据库系统.交互式界面.应用结构 ...

随机推荐

  1. sin, miss the mark, correct our aim and try again

    Guilt should only be a call to action. When we see that we "missed the mark"(the meaning o ...

  2. LR录制https协议报证书错误,导航已阻止

    使用IE浏览器录制https协议报证书错误,导航已阻止,修改如下配置文件:

  3. pcA降维算法

    http://ufldl.stanford.edu/wiki/index.php/主成分分析 if ~exist('train_IM_all','var')||~exist('train_LA_all ...

  4. IntelliJ IDEA13.1.3+Scala2.11.1环境搭建

    fesh个人实践,欢迎经验交流!本文Blog地址:http://www.cnblogs.com/fesh/p/3805611.html Intellij IDEA的使用性非常好,是一个非常优秀的IDE ...

  5. grep 和 wc命令 --- !管道命令!

    Linux系统中grep命令是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹 配的行打印出来.grep全称是Global Regular Expr ession Print,表示全局正则表 ...

  6. C#语法灵活运用之排列组合算法

    今天群里有朋友求一个排列组合算法,题目是给定长度,输出所有指定字母的组合. 如指定字母a.b.c.d.e.f,长度为2,则结果应为:aa.ab.ac ... ef.ff. 有朋友给出算法,很有特色: ...

  7. WinForm窗体PropertyGrid控件的使用

    使用过 Microsoft Visual Basic 或 Microsoft Visual Studio .NET的朋友,一定使用过属性浏览器来浏览.查看或编辑一个或多个对象的属性..NET 框架 P ...

  8. 统计学习方法笔记(KNN)

    k近邻法(k-nearest neighbor,k-NN) 输入:实例的特征向量,对应于特征空间的点:输出:实例的类别,可以取多类. 分类时,根据其k个最近邻的训练实例的类别,通过多数表决等方式进行预 ...

  9. 自定义安装php开发环境(1)--apache和php整合

    第一步:安装apache 第二步:下载php核心包php-5.3.3-Win32-VC6-x86.zip.并放入开发环境文件夹C:/phpenv/文件夹下 第三步: 将apache 和php 整合 也 ...

  10. CoreLocation框架的使用---定位,求两地距离

    前言: 在iOS开发中,有关导航,周边的开发,必须基于2个框架: Map Kit :用于地图展示 Core Location :用于地理定位   用户隐私的保护 从iOS 6开始,苹果在保护用户隐私方 ...