C#中Abstract和Virtual

【abstract】

abstract 修饰符指示所修饰的内容缺少实现或未完全实现。 abstract 修饰符可用于类、方法、属性、索引器和事件。 在类声明中使用 abstract 修饰符以指示某个类只能是其他类的基类。 标记为抽象或包含在抽象类中的成员必须通过从抽象类派生的类来实现。

示例:

在此例中,类 Square 必须提供 Area 的实现,因为它派生自 ShapesClass

abstract class ShapesClass
{
  abstract public int Area();}
class Square : ShapesClass
{
  int side = 0;

  public Square(int n)
  {
    side = n;
  }
  // Area method is required to avoid
  // a compile-time error.
  public override int Area()
  {
    return side * side;
  }

  static void Main()
  {
    Square sq = new Square(12);
    Console.WriteLine("Area of the square = {0}", sq.Area());
  }

  interface I
  {
    void M();
  }
  abstract class C : I
  {
    public abstract void M();
  }
}
// Output: Area of the square = 144

抽象类具有以下特性:

  • 抽象类不能实例化。
  • 抽象类可以包含抽象方法和抽象访问器。
  • 不能用 sealed 修饰符修饰抽象类,因为这两个修饰符的含义是相反的。 采用 sealed 修饰符的类无法继承,而 abstract 修饰符要求对类进行继承。
  • 从抽象类派生的非抽象类必须包括继承的所有抽象方法和抽象访问器的实际实现。

在方法或属性声明中使用 abstract 修饰符以指示方法或属性不包含实现。

抽象方法具有以下特性:

  • 抽象方法是隐式的虚方法。
  • 只允许在抽象类中使用抽象方法声明。
  • 因为抽象方法声明不提供实际的实现,所以没有方法体;方法声明只是以一个分号结束,并且在签名后没有大括号 ({ })。 例如:
    public abstract void MyMethod();

    实现由一个重写方法重写提供,此重写方法是非抽象类的一个成员。

  • 在抽象方法声明中使用 static 或 virtual 修饰符是错误的。除了在声明和调用语法上不同外,抽象属性的行为与抽象方法一样。
  • 在静态属性上使用 abstract 修饰符是错误的。
  • 在派生类中,通过包括使用 override 修饰符的属性声明,可以重写抽象的继承属性。
  • 实现接口的抽象类可以将接口方法映射到抽象方法上。 例如:

            interface I
            {
                void M();
            }
            abstract class C : I
            {
                public abstract void M();
            }

示例:

在本例中,DerivedClass 类是从抽象类 BaseClass 派生的。 抽象类包含一个抽象方法 AbstractMethod 和两个抽象属性 X 和 Y

    abstract class BaseClass   // Abstract class
    {
        protected int _x = 100;
        protected int _y = 150;
        public abstract void AbstractMethod();   // Abstract method
        public abstract int X    { get; }
        public abstract int Y    { get; }
    }

    class DerivedClass : BaseClass
    {
        public override void AbstractMethod()
        {
            _x++;
            _y++;
        }

        public override int X   // overriding property
        {
            get
            {
                return _x + 10;
            }
        }

        public override int Y   // overriding property
        {
            get
            {
                return _y + 10;
            }
        }

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

在上面的示例中,如果尝试通过使用下面的语句将抽象类实例化:

BaseClass bc = new BaseClass();   // Error 

将出现错误,指出编译器无法创建抽象类“BaseClass”的实例。

【virtual】

virtual 关键字用于修饰方法、属性、索引器或事件声明,并使它们可以在派生类中被重写。 例如,此方法可被任何继承它的类重写。

public virtual double Area()
{
    return x * y;
} 

调用虚方法时,将为重写成员检查该对象的运行时类型。 将调用大部分派生类中的该重写成员,如果没有派生类重写该成员,则它可能是原始成员。

默认情况下,方法是非虚拟的。 不能重写非虚方法。

virtual 修饰符不能与 staticabstract, private 或 override 修饰符一起使用。 下面的示例演示一个虚拟属性:

    class MyBaseClass
    {
        // virtual auto-implemented property. Overrides can only
        // provide specialized behavior if they implement get and set accessors.
        public virtual string Name { get; set; }

        // ordinary virtual property with backing field
        private int num;
        public virtual int Number
        {
            get { return num; }
            set { num = value; }
        }
    }

    class MyDerivedClass : MyBaseClass
    {
        private string name;

       // Override auto-implemented property with ordinary property
       // to provide specialized accessor behavior.
        public override string Name
        {
            get
            {
                return name;
            }
            set
            {
                if (value != String.Empty)
                {
                    name = value;
                }
                else
                {
                    name = "Unknown";
                }
            }
        }

    }

除了声明和调用语法不同外,虚拟属性的行为与抽象方法一样。

  • 在静态属性上使用 virtual 修饰符是错误的。
  • 通过包括使用 override 修饰符的属性声明,可在派生类中重写虚拟继承属性。

示例:

在该示例中,Shape 类包含 xy 两个坐标和 Area() 虚方法。 不同的形状类,如 CircleCylinder 和 Sphere 继承 Shape 类,并为每个图形计算表面积。 每个派生类都有各自的 Area() 重写实现。

通知继承的类 Circle、 Sphere和 Cylinder 初始化基类的所有使用构造函数,如以下声明所示。

public Cylinder(double r, double h): base(r, h) {} 

下面的过程通过调用 Area() 方法的适当实现计算并显示由每个图形的合适区域,根据与该方法的对象。

    class TestClass
    {
        public class Shape
        {
            public const double PI = Math.PI;
            protected double x, y;
            public Shape()
            {
            }
            public Shape(double x, double y)
            {
                this.x = x;
                this.y = y;
            }

            public virtual double Area()
            {
                return x * y;
            }
        }

        public class Circle : Shape
        {
            public Circle(double r) : base(r, 0)
            {
            }

            public override double Area()
            {
                return PI * x * x;
            }
        }

        class Sphere : Shape
        {
            public Sphere(double r) : base(r, 0)
            {
            }

            public override double Area()
            {
                return 4 * PI * x * x;
            }
        }

        class Cylinder : Shape
        {
            public Cylinder(double r, double h) : base(r, h)
            {
            }

            public override double Area()
            {
                return 2 * PI * x * x + 2 * PI * x * y;
            }
        }

        static void Main()
        {
            double r = 3.0, h = 5.0;
            Shape c = new Circle(r);
            Shape s = new Sphere(r);
            Shape l = new Cylinder(r, h);
            // Display results:
            Console.WriteLine("Area of Circle   = {0:F2}", c.Area());
            Console.WriteLine("Area of Sphere   = {0:F2}", s.Area());
            Console.WriteLine("Area of Cylinder = {0:F2}", l.Area());
            }
        }
        /*
            Output:
            Area of Circle   = 28.27
            Area of Sphere   = 113.10
            Area of Cylinder = 150.80
        */
时间: 2024-10-25 22:19:55

C#中Abstract和Virtual的相关文章

C#中Abstract和Virtual的区别

c# 中 Abstract和Virtual比较容易混淆,都与继承有关,并且涉及override的使用.下面讨论一下二者的区别: 一.Virtual方法(虚方法) virtual 关键字用于在基类中修饰方法.virtual的使用会有两种情况: 情况1:在基类中定义了virtual方法,但在派生类中没有重写该虚方法.那么在对派生类实例的调用中,该虚方法使用的是基类定义的方法. 情况2:在基类中定义了virtual方法,然后在派生类中使用override重写该方法.那么在对派生类实例的调用中,该虚方法

C#中Abstract和Virtual[转载]

原文:http://www.cnblogs.com/blsong/archive/2010/08/12/1798064.html 在C#的学习中,容易混淆virtual方法和abstract方法的使用,现在来讨论一下二者的区别.二者都牵涉到在派生类中与override的配合使用. 一.Virtual方法(虚方法) virtual 关键字用于在基类中修饰方法.virtual的使用会有两种情况: 情况1:在基类中定义了virtual方法,但在派生类中没有重写该虚方法.那么在对派生类实例的调用中,该虚

C#中Abstract和Virtual(转)

在C#的学习中,容易混淆virtual方法和abstract方法的使用,现在来讨论一下二者的区别.二者都牵涉到在派生类中与override的配合使用. 一.Virtual方法(虚方法) virtual 关键字用于在基类中修饰方法.virtual的使用会有两种情况: 情况1:在基类中定义了virtual方法,但在派生类中没有重写该虚方法.那么在对派生类实例的调用中,该虚方法使用的是基类定义的方法. 情况2:在基类中定义了virtual方法,然后在派生类中使用override重写该方法.那么在对派生

C#继承中abstract、virtual、override和new

abstract 详细参考:https://msdn.microsoft.com/zh-cn/library/sf985hc5.aspx abstract 修饰符指示所修饰的内容缺少实现或未完全实现. abstract 修饰符可用于类.方法.属性.索引器和事件. 在类声明中使用 abstract 修饰符以指示某个类只能是其他类的基类. 标记为抽象或包含在抽象类中的成员必须通过从抽象类派生的类来实现. 抽象类具有以下特性: - 抽象类不能实例化. - 抽象类可以包含抽象方法和抽象访问器. - 不能

c#中的interface abstract与virtual介绍

abstract 与virtual : 方法重写时都使用 override 关键字,interface中的方法和abstract方法都要求实现 interface用来声明接口1.只提供一些方法规约,不提供方法主体.  如: 复制代码 代码如下: public interface IPerson{    void getName();//不包含方法主体} 2.方法不能用public abstract等修饰,无字段变量,无构造函数.3.方法可包含参数.  如 复制代码 代码如下: public in

9 abstract 和 Virtual 之间的区别

(1) abstract方法没有具体的实现,同时必须被覆写 (2) 虚(Virtual)方法可以没有具体的实现,也不一定必须覆写(虚方法定义时,可以没有具体的实现代码,但是必须创建方法体:即必须有方法的左右花括号). (3) 抽象方法不可以使用base.method()方式调用,但是虚方法是可以的 //定义一个抽象方法 using System; using System.Collections.Generic; using System.Linq; using System.Text; usi

C# Abstract和Virtual

在C#的学习中,容易混淆virtual方法和abstract方法的使用,现在来讨论一下二者的区别.二者都牵涉到在派生类中与override的配合使用. 一.Virtual方法(虚方法) virtual 关键字用于在基类中修饰方法.virtual的使用会有两种情况: 情况1:在基类中定义了virtual方法,但在派生类中没有重写该虚方法.那么在对派生类实例的调用中,该虚方法使用的是基类定义的方法. 情况2:在基类中定义了virtual方法,然后在派生类中使用override重写该方法.那么在对派生

【C#】Abstract和Virtual的区别

一.Virtual方法(虚方法) virtual 关键字用于在基类中修饰方法.virtual的使用会有两种情况: 情况1:在基类中定义了virtual方法,但在派生类中没有重写该虚方法.那么在对派生类实例的调用中,该虚方法使用的是基类定义的方法. 情况2:在基类中定义了virtual方法,然后在派生类中使用override重写该方法.那么在对派生类实例的调用中,该虚方法使用的是派生重写的方法. 二.Abstract方法(抽象方法) abstract关键字只能用在抽象类中修饰方法,并且没有具体的实

C#基础知识(base、this、new、override、abstract、virtual、static)

前言 本文主要来讲解一下C#中,自己觉得掌握的不怎么样或者用的不多,不太熟悉的关键字,主要包括base.this.new.override.abstract.virtual以及针对static字段和static构造函数之间的执行问题. base关键字 base 关键字用于在派生类中实现对基类公有或者受保护成员的访问,但是只局限在构造函数.实例方法和实例属性访问器中: 调用基类上已被其他方法重写的方法. public class Father { public virtual void Say()