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. leetcode 6. ZigZag Conversion

    https://leetcode.com/problems/zigzag-conversion/ 题目: 将字符串转化成zigzag模式. 例如 "abcdefghijkmlnpq" ...

  2. DelphiXE2 DataSnap开发技巧收集

    DelphiXE2 DataSnap开发技巧收集 作者:  2012-08-07 09:12:52     分类:Delphi     标签: 作为DelphiXE2 DataSnap开发的私家锦囊, ...

  3. Delphi2010中DataSnap高级技术(7)—TDSServerClass中Lifecycle生命周期三种属性说明

    Lifecycle 三种属性: Session.Invocation.Server 这三种属性都用在什么情况,有什么要注意的事项,Delphi2010中罕有说明. 如果乱用这三种属性,你的服务程序有可 ...

  4. 2 Egg Problem

    继续我们的推理问题之旅,今天我们要对付的是一个Google的面试题:Two Egg Problem. 我们开始吧! No.2  Google Interview Puzzle : 2 Egg Prob ...

  5. lua代码设置unity对象的基础属性

    设置对象的父节点: wall.transform:SetParent(GameObject.Find("Walls").transform) 设置颜色: wall:GetCompo ...

  6. react js 之生命周期

    react redux 结合是目前比较流行的前端开发框架,主要基于react 中的state 树为数据模型,借助redux 来控制 state 数据:下面直接从代码层面解析该框架中一个react 组件 ...

  7. SQL Cumulative Sum累积求和

    期望结果:  ID  VAL  CumSum  1  10  10  2  20  30  3  30  60 方法一: 使用分析函数 select id,val,sum(val) over ( or ...

  8. 背包九讲 && 题目

    ★.背包求方案数的时候,多重背包是不行的,因为产生重复的背包会有多种情况. ★.背包记录路径的时候,其实是不行的,因为更新了12的最优解,如果它依赖于6这个背包,然后你后面改变了6这个背包,就GG 1 ...

  9. db2 with ur

    这几天查询DB2数据库,老遇到select * from XXX with ur, 好奇ur是什么作用,现在记录一下. DB2中,共有四种隔离级:RS,RR,CS,UR,DB2提供了这4种不同的保护级 ...

  10. ArcMap 操作笔记

    1.SQL查询(in) select * from table where PointID in ('1','2')