抽象方法与虚方法的区别

一、抽象方法:

只在抽象类中定义,方法修饰符不能使用 private , virtual, static.

public abstract class People   //声明一个抽象类
{
    public abstract void study();  //抽象方法只能定义在抽象类中。
}
public class Student:People   //继承抽象类
{
    public  override void study()     //重写抽象类的抽象方法
    {
        Console.WriteLine("好好学习,天天向上!");
    }
}
public class Program
{
    static void Main(string[] args)
    {
        Student t= new Student();//实例化派生类
        People  p= t;   //使用派生类对象实例化抽象类
        //以上两句等价于  People p = new Student();//使用派生类对象实例化抽象类;
        p.study(); //使用抽象类对象调用抽象类中的抽象方法study    
    }
}

总结:

(1)象方法只能声明在抽象类中,使用关键字abstract

(2)抽象类中的抽象方法必须被子类重写。

【抽象方法没有方法体,子类必须重写方法体!!,因此抽象方法可以看成是一个没有方法体的虚方法】

二、虚方法:

使用virtual修饰的方法:
虚方法可以有方法体。

public class BaseClass         //创建一个基类
{
    public virtual string GetName()    //使用virtual关键字创建父类中的虚方法
    {
        return "父类虚方法体":     
    }
}
public class SubClass:BaseClass    //子类继承父类
{
    public override string GetName();   //子类重写父类虚方法
    {
        return "重写父类虚方法!";
    }
}

以上的示例:父类中的虚方法被派生类重写了。
注意事项:

  • virtual修饰符不能与private、static、abstract、override修饰符同时使用。
  • override修饰符不能与new 、static、virtual修饰符同时使用,并且重写方法只能用于重写基类中的虚方法。

虚函数的限制:

  • 虚函数仅适用于有继承关系的类对象,所以只有类的成员函数才能说明为虚函数;
  • 静态成员函数、内联函数、构造函数不能是虚函数;
  • 析构函数可以是虚函数。

三、两者区别:

总结:抽象方法是只有方法名称,没有方法体(也就是没有方法具体实现),子类必须重写父类抽象方法;
虚函数是该方法有方法体,但是子类可以覆盖,也可不覆盖。
(1)虚方法有方法体,抽象方法没有方法体。抽象方法是一种强制派生类覆盖的方法,否则派生类将不能被实例化;
(2)抽象方法只能在抽象类中声明,虚方法不是;
(3)派生类必须重写抽象类中的抽象方法,虚方法则不必要。


四、abstract详细讲解

abstract可以用来修饰类、方法、属性、索引器时间,这里不包括字段. 使用abstrac修饰的类,该类只能作为其他类的基类,不能实例化,即不能new一个对象。而且abstract修饰的成员在派生类中必须全部实现,不允许部分实现,否则编译异常. 如:

using System;
namespace ConsoleApplication 
{ 
  class Program 
  { 
    static void Main(string[] args) 
    { 
      BClass b = new BClass(); 
      b.m1(); 
    } 
  } 
  ........
}

抽象类拥有如下特征:

  1. 抽象类不能被实例化, 但可以有实例构造函数, 类是否可以实例化取决于是否拥有实例化的权限 (对于抽象类的权限是abstract, 禁止实例化),即使不提供构造函数, 编译器也会提供默认构造函数;

  2. 抽象类可以包含抽象方法和访问器;

  3. 抽象类不能使用sealed修饰, sealed意为不能被继承;

  4. 所有继承自抽象类的非抽象类必须实现所有的抽象成员,包括方法,属性,索引器,事件;

abstract修饰的方法有如下特征:

  1. 抽象方法即是虚拟方法(隐含);

  2. 抽象方法只能在抽象类中声明;

  3. 因为抽象方法只是声明, 不提供实现, 所以方法只以分号结束,没有方法体,即没有花括号部分;如
    public abstract void MyMethod();

  4. override修饰的覆盖方法提供实现,且只能作为非抽象类的成员;

  5. 在抽象方法的声明上不能使用virtual或者是static修饰.即不能是静态的,又因为abstract已经是虚拟的,无需再用virtual强调.

抽象属性与抽象方法的不同:

抽象属性尽管在行为上与抽象方法相似,但仍有有如下不同:

  1. 不能在静态属性上应用abstract修饰符;

  2. 抽象属性在非抽象的派生类中覆盖重写,使用override修饰符;

抽象类与接口:

  1. 抽象类必须提供所有接口成员的实现;
  2. 继承接口的抽象类可以将接口的成员映射位抽象方法.

抽象类实例分析:

interface I 
{ 
    void M(); 
} 
abstract class C:I 
{ 
    public abstract void M(); 
} 
抽象类实例: 
// abstract_keyword.cs 
// 抽象类 
using System; 
abstract class BaseClass // 抽象类 
{ 
    protected int _x = 100; //抽象类可以定义字段,但不可以是抽象字段,也没有这一说法. 
    protected int _y = 150; 
    public BaseClass(int i) //可以定义实例构造函数,仅供派生的非抽象类调用; 
    {                       //这里显式提供构造函数,编译器将不再提供默认构造函数. 
        fielda = i; 
    } 
    public BaseClass() 
    { } 
    private int fielda; 
    public static int fieldsa = 0; 
    public abstract void AbstractMethod(); // 抽象方法 
    public abstract int X { get; } //抽象属性 
    public abstract int Y { get; } 
    public abstract string IdxString { get; set; } //抽象属性 
    public abstract char this[int i] { get; } //抽象索引器 
}
class DerivedClass : BaseClass 
{ 
    private string idxstring; 
    private int fieldb; 
    //如果基类中没有定义无参构造函数,但存在有参数的构造函数, 
    //那么这里派生类得构造函数必须调用基类的有参数构造函数,否则编译出错 
    public DerivedClass(int p) 
    : base(p) //这里的:base(p)可省略,因为基类定义了默认的无参构造函数 
    { 
        fieldb = p; 
    } 
    public override string IdxString //覆盖重新属性 
    { 
        get
        { 
            return idxstring; 
        } 
        set
        { 
            idxstring = value; 
        } 
    } 
    public override char this[int i] //覆盖重写索引器 
    { 
        get { return IdxString[i]; } 
    } 
    public override void AbstractMethod() 
    { 
        _x++; 
        _y++; 
    }
    public override int X // 覆盖重写属性
    {
        get{ return _x + 10; }
    }

    public override int Y // 覆盖重写属性
    {
        get{ return _y + 10; }
    }

    static void Main()
    {
        DerivedClass o = new DerivedClass(1);
        o.AbstractMethod();
        Console.WriteLine("x = {0}, y = {1}", o.X, o.Y);
    }
}

   转载规则


《抽象方法与虚方法的区别》 LoveBin 采用 知识共享署名 4.0 国际许可协议 进行许可。
  目录