Abstract:

  1、用途:提供一个可供多个派生类共享的通用基类定义。

  2、抽象类也可以定义抽象方法,方法是将关键字 abstract 添加到方法的返回类型的前面(抽象方法没有实现,所以方法定义后面是分号,而不是常规的方法块),

     抽象类的派生类必须实现所有抽象方法。当抽象类从基类继承虚方法时,抽象类可以使用抽象方法重写该虚方法,

public class D
{
  public virtual void DoWork(int i)
  {
    // Original implementation.
  }
}
 
public abstract class E : D
{
  public abstract override void DoWork(int i);
}
 
public class F : E
{
  public override void DoWork(int i)
  {
    // New implementation.
  }
}
public abstract class Shape
{
private string name; public Shape(string s)
{
// calling the set accessor of the Id property.
Id = s;
} public string Id
{
get
{
return name;
} set
{
name = value;
}
} // Area is a read-only property - only a get accessor is needed:
public abstract double Area
{
get;
} public override string ToString()
{
return Id + " Area = " + string.Format("{0:F2}", Area);
}
}
public class Square : Shape
{
private int side; public Square(int side, string id)
: base(id)
{
this.side = side;
} public override double Area
{
get
{
// Given the side, return the area of a square:
return side * side;
}
}
} public class Circle : Shape
{
private int radius; public Circle(int radius, string id)
: base(id)
{
this.radius = radius;
} public override double Area
{
get
{
// Given the radius, return the area of a circle:
return radius * radius * System.Math.PI;
}
}
} public class Rectangle : Shape
{
private int width;
private int height; public Rectangle(int width, int height, string id)
: base(id)
{
this.width = width;
this.height = height;
} public override double Area
{
get
{
// Given the width and height, return the area of a rectangle:
return width * height;
}
}
}

class TestClass
{
static void Main()
{
Shape[] shapes =
{
new Square(, "Square #1"),
new Circle(, "Circle #1"),
new Rectangle( , , "Rectangle #1")
}; System.Console.WriteLine("Shapes Collection");
foreach (Shape s in shapes)
{
System.Console.WriteLine(s);
}
}
}
//输出:
//Shapes Collection
//Square #1 Area = 25.00
//Circle #1 Area = 28.27
//Rectangle #1 Area = 20.00

  注:

    1、C#中Abstract和Virtual

      一、Virtual方法(虚方法)

      virtual 关键字用于在基类中修饰方法。virtual的使用会有两种情况:

        情况1:在基类中定义了virtual方法,但在派生类中没有重写该虚方法。那么在对派生类实例的调用中,该虚方法使用的是基类定义的方法。

        情况2:在基类中定义了virtual方法,然后在派生类中使用override重写该方法。那么在对派生类实例的调用中,该虚方法使用的是派生重写的方法。

      二、Abstract方法(抽象方法)

      abstract关键字只能用在抽象类中修饰方法,并且没有具体的实现。抽象方法的实现必须在派生类中使用override关键字来实现。

    2、接口和抽象类:

       最本质的区别:抽象类是一个不完全的类,是对对象的抽象,而接口是一种行为规范。

       1、抽象类中可以有非抽象方法;

        但接口中只提供一些方法规约,不提供方法主体,方法不能用public abstract等修饰,无字段变量,无构造函数。且实现interface的类必须实现接口的各个方法。

      2、抽象类虽不能实例化(然而可以创建一个变量,其类型是一个抽象类,并让它指向具体子类的一个实例),但可以有构造函数,抽象类的构造函数用来初始化抽象类的一些字段,而这一切都在抽象类的派生类实例化之前发生。不仅如此,抽线类的构造函数还有一种巧妙应用:就是在其内部实现子类必须执行的代码。

      

class Program
{
static void Main(string[] args)
{
Employee employee = new Employee();
Console.WriteLine(employee.ID);
Console.ReadKey();
}
}
public abstract class Base
{
private Guid _id;
public Base()
{
this._id = Guid.NewGuid();
}
public Guid ID
{
get { return this._id; }
}
}
public class Employee : Base
{ }

    3、一个类只能继承一个抽象类,但可以实现多个接口。

    4、当一个类继承了一个抽象类,它必须要重写父类抽象类中的抽象方法,如果不去重写父类抽象方法的实例,那么这个类也是抽象类(这个抽象子类,直到重写这个抽象方法的实例为止,才能摆脱抽象的命运)。

        实现接口也必须实现接口中的每个行为。

一个类可以同时继承多个“接口”,但只能继承一个“抽象类”

  

    

public class Square : Shape
{
  private int side;
 
  public Square(int side, string id)
    : base(id)
  {
    this.side = side;
  }
 
  public override double Area
  {
    get
    {
      // Given the side, return the area of a square:
      return side * side;
    }
  }
}
 
public class Circle : Shape
{
  private int radius;
 
  public Circle(int radius, string id)
    : base(id)
  {
    this.radius = radius;
  }
 
  public override double Area
  {
    get
    {
      // Given the radius, return the area of a circle:
      return radius * radius * System.Math.PI;
    }
  }
}
 
public class Rectangle : Shape
{
  private int width;
  private int height;
 
  public Rectangle(int width, int height, string id)
    : base(id)
  {
    this.width = width;
    this.height = height;
  }
 
  public override double Area
  {
    get
    {
      // Given the width and height, return the area of a rectangle:
      return width * height;
    }
  }
}
 
 
 

接口(interface)可以说成是抽象类的一种特例,接口中的所有方法都必须是抽象的。接口中的方法定义默认为public abstract类型,接口中的成员变量类型默认为public static final。

下面比较一下两者的语法区别:

1.抽象类可以有构造方法,接口中不能有构造方法。

2.抽象类中可以有普通成员变量,接口中没有普通成员变量

3.抽象类中可以包含非抽象的普通方法,接口中的所有方法必须都是抽象的,不能有非抽象的普通方法。

4. 抽象类中的抽象方法的访问类型可以是public,protected和(默认类型,虽然eclipse下不报错,但应该也不行),但接口中的抽象方法只能是public类型的,并且默认即为public abstract类型。

5. 抽象类中可以包含静态方法,接口中不能包含静态方法

6. 抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任意,但接口中定义的变量只能是public static final类型,并且默认即为public static final类型。

7. 一个类可以实现多个接口,但只能继承一个抽象类。

下面接着再说说两者在应用上的区别:

接口更多的是在系统架构设计方法发挥作用,主要用于定义模块之间的通信契约。

而抽象类在代码实现方面发挥作用,可以实现代码的重用

C# abstract的更多相关文章

  1. abstract与interface之房祖名张默版

    最近把java基础知识拿出来看看,看到abstract与interface的时候,觉得有点模糊,好像面试官也喜欢问这个问题.我在百度了查了好长时间,觉得讲算比较清楚的是那篇讲 Door,然后想要带个报 ...

  2. [Erlang 0111] Erlang Abstract Format , Part 2

       上回书,我们说到飞天玉虎蒋伯芳来到蜈蚣岭,不是,重来,上回咱们说到可以在Erlang Shell里面手工构造,加载并调用一个模块.在那个demo里面,我把多个Form单独生成出来,最后放在一起做 ...

  3. [Erlang 0110] Erlang Abstract Format , Part 1

    Erlang Abstract Format并不难懂,只是枯燥一点罢了,如果把Abstract Format的文档翻译出来,其实就是Erlang教科书中语法入门的部分. Erlang Abstract ...

  4. C#中Abstract和Virtual的区别

    c# 中 Abstract和Virtual比较容易混淆,都与继承有关,并且涉及override的使用.下面讨论一下二者的区别: 一.Virtual方法(虚方法) virtual 关键字用于在基类中修饰 ...

  5. Java Abstract Class & Interface

    一. 抽象类 1. 抽象类:包含了一个抽象方法的类就是抽象类 2. 抽象方法:声明而未被实现的方法,用关键字abstract声明 3. 抽象类被子类继承,子类(如果不是抽象类)必须重写(overrid ...

  6. java关键字extends(继承)、Supe(父类引用空间)、 This(方法调用者对象)、Instanceof(实例类型-判断对象是否属于某个类)、final(最终)、abstract(抽象) 、interface(接口)0

    java 继承使用关键字extends   继承的作用:减少代码量,优化代码 继承的使用注意点: 1子类不能继承父类的私有变量 2.子类不能继承父类的构造方法 3.子类在调用自己的构造方法时 会默认调 ...

  7. abstract与interface的区别

    abstract的用法: //通过abstract 关键字修饰的类叫抽象类. abstract class Animal { String name; String color; abstract p ...

  8. Delphi之静态方法,虚方法virtual,动态dynamic,抽象abstract,消息

    Delphi之静态方法,虚方法virtual,动态dynamic,抽象abstract,消息 http://www.cnblogs.com/zhwx/archive/2012/08/28/266055 ...

  9. c#中abstract与virtua、overridel的用法

    1.abstract 抽象方法 ,virtual 虚方法 ,override 重载函数 父类A.m() 子类B.m()   abstract的方法父类可以不实现,让子类去重写(重写=overwrite ...

  10. 一张图看懂normal,static,sealed,abstract 的 区别

    +-------------------------+---+--------+--------+--------+----------+ | Class Type | | normal | stat ...

随机推荐

  1. document.createElement()方法

    document.createElement()是在对象中创建一个对象,主要和appendChild() 方法或者insertBefore() 方法联合使用. appendChild() 方法在节点的 ...

  2. kafka:一个分布式消息系统

    1.背景 最近因为工作需要,调研了追求高吞吐的轻量级消息系统Kafka,打算替换掉线上运行的ActiveMQ,主要是因为明年的预算日流量有十亿,而ActiveMQ的分布式实现的很奇怪,所以希望找一个适 ...

  3. redis的安装和启动

    Windows下Redis的安装及PHP扩展使用 时间 2014-10-28 17:47:09  CSDN博客 原文  http://blog.csdn.net/wyqwclsn/article/de ...

  4. iOS开发XCODE5 SVN配置 使用办法 (转) 收藏一下

    标签: xcode5svn xcodesvn使用 xcode自带的svn xcodesvn版本操作 xcode自带svn版本   这两天响应老板要求,把所有代码放到公司的SVN服务器上,按照我的想法肯 ...

  5. StaticPagedList

    估计是因为水平原因,之前看别人写的用pagedList分页,老是云里雾里的.下面把自己写的整理一下放在上面.这里的List为对应页面展示的内容.不用查询所有. Action: public Actio ...

  6. 关于AFNetworking菊花转圈圈的问题

    刚开始接触AFN的时候,发现菊花老是不转,百度到大神的博客上,说AFN里面的API的网络加载菊花默认是关闭的(才发现默认情况下AFN的转圈圈的菊花是关闭的)需要手动打开才能够显示转圈圈,打开的方法是: ...

  7. uvm - dut

    module dut(clk, rst_n, rxd, rx_dv, txd, tx_en); input clk; input rst_n; :] rxd; input rx_dv; :] txd; ...

  8. VScode常用几个前端插件live HTML previewer和debugger for chrome的配置

    之前一直都是用sublime Text和chrome配合来写前端的页面,自从知道了有liveReload这个神奇的插件之后感觉爽翻了啊.好吧跑远了........ 话说最近微软搞了个VScode,听说 ...

  9. 关于MySQL的CRUD操作

    一.清除mysql表中数据 delete from 表名; truncate table 表名; 不带where参数的delete语句可以删除mysql表中所有内容,使用truncate table也 ...

  10. java多线程详解(3)-线程的互斥与同步

    前言:前一篇文章主要描述了多线程中访成员变量与局部变量问题,我们知道访成员变量有线程安全问题,在多线程程序中 我们可以通过使用synchronized关键字完成线程的同步,能够解决部分线程安全问题 在 ...