一:abstract 修饰符可以和类、方法、属性、索引器及事件一起使用。在类声明中使用 abstract 修饰符以指示某个类只能是其他类的基类。标记为抽象或包含在抽象类中的成员必须通过从抽象类派生的类来实现。
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());
}
}
// Output: Area of the square = 144
1:抽象类具有以下特性:
抽象类不能实例化。
抽象类可以包含抽象方法和抽象访问器。
不能用 sealed(C# 参考) 修饰符修改抽象类,因为 sealed 会使得抽象类无法被继承。
从抽象类派生的非抽象类必须包括继承的所有抽象方法和抽象访问器的实实现。
在方法或属性声明中使用 abstract 修饰符以指示方法或属性不包含实现。
2:抽象方法具有以下特性:
抽象方法是隐式的虚方法。
只允许在抽象类中使用抽象方法声明。
因为抽象方法声明不提供实际的实现,所以没有方法体;方法声明只是以一个分号结束,并且在签名后没有大括号 ({ })。
在抽象方法声明中使用 static 或 virtual 修饰符是错误的。
除了在声明和调用语法上不同外,抽象属性的行为与抽象方法一样。
在静态属性上使用 abstract 修饰符是错误的。
在派生类中,通过包括使用 override 修饰符的属性声明,可以重写抽象的继承属性。
3:抽象类必须为所有接口成员提供实现。
实现接口的抽象类可以将接口方法映射到抽象方法上。例如:
interface I
{
void M();
}
abstract class C : I
{
public abstract void M();
}
二:virtual 关键字用于修饰方法、属性、索引器或事件声明,并使它们可以在派生类中被重写。例如,此方法可被任何继承它的类重写。
1:virtual 修饰符不能与 static、abstract, private 或 override 修饰符一起使用。
除了声明和调用语法不同外,虚拟属性的行为与抽象方法一样。
在静态属性上使用 virtual 修饰符是错误的。
通过包括使用 override 修饰符的属性声明,可在派生类中重写虚拟继承属性。
三:interface 接口只包含方法、属性、事件或索引器的签名。成员的实现是在实现接口的类或结构中完成的,如下面的示例所示:
1:只提供一些方法规约,不提供方法主体. 如:
public interface IPerson
{
void getName();//不包含方法主体
}
2:方法不能用public abstract等修饰,无字段变量,无构造函数。
3:方法可包含参数。 如
public interface IPerson
{
void getAge(string s);
}
4:显示接口实现,如果类实现两个接口,并且这两个接口包含具有相同签名的成员,那么在类中实现该成员将导致两个接口都使用该成员作为它们的实现。例如:
interface IControl
{
void Paint();
}
interface ISurface
{
void Paint();
}
public class SampleClass : IControl, ISurface
{
void IControl.Paint()
{
System.Console.WriteLine("IControl.Paint");
}
void ISurface.Paint()
{
System.Console.WriteLine("ISurface.Paint");
}
}
SampleClass obj = new SampleClass();
//obj.Paint(); // Compiler error.
IControl c = (IControl)obj;
c.Paint(); // Calls IControl.Paint on SampleClass.
ISurface s = (ISurface)obj;
s.Paint(); // Calls ISurface.Paint on SampleClass.
5:显式实现还用于解决两个接口分别声明具有相同名称的不同成员(如属性和方法)的情况:为了同时实现两个接口,类必须对属性 P 和/或方法 P 使用显式实现以避免编译器错误。例如:
interface ILeft
{
int P { get;}
}
interface IRight
{
int P();
}
class Middle : ILeft, IRight
{
public int P() { return 0; }
int ILeft.P { get { return 0; } }
}
四:override 要扩展或修改继承的方法、属性、索引器或事件的抽象实现或虚实现,必须使用 override 修饰符。
1:override 方法提供从基类继承的成员的新实现。由 override 声明重写的方法称为重写基方法。重写的基方法必须与 override 方法具有相同的签名。有关继承的信息,请参见继承(C# 编程指南)。
2:不能重写非虚方法或静态方法。重写的基方法必须是 virtual、abstract 或 override 的。
3:override 声明不能更改 virtual 方法的可访问性。override 方法和 virtual 方法必须具有相同的访问级别修饰符。
4:不能使用 new、static、virtual 或 abstract 修饰符来修改 override 方法。
5:重写属性声明必须指定与继承属性完全相同的访问修饰符、类型和名称,并且被重写的属性必须是 virtual、abstract 或 override 的。
五:new 在用作修饰符时,new 关键字可以显式隐藏从基类继承的成员。隐藏继承的成员时,该成员的派生版本将替换基类版本。虽然可以在不使用 new 修饰符的情况下隐藏成员,但会生成警告。如果使用 new 显式隐藏成员,则会取消此警告,并记录要替换为派生版本这一事实。
1:对同一成员同时使用 new 和 override 是错误的做法,因为这两个修饰符的含义互斥。new 修饰符会用同样的名称创建一个新成员并使原始成员变为隐藏的。override 修饰符会扩展继承成员的实现。
六:new 和 override 的区别,即重写和隐藏的区别
class Car
{
public virtual void DescribeCar()
{
System.Console.WriteLine("Four wheels and an engine.");
}
}
class ConvertibleCar : Car
{
//基类方法不必是虚拟的,但结果是一样的.//破坏多态
//ConvertibleCar car2 = new ConvertibleCar();调用自身的
//cars[1] = new ConvertibleCar();调用基类的,尽管隐藏了基类的执行代码,但仍可以通过基类访问它。
public new void DescribeCar()
{
base.DescribeCar();
System.Console.WriteLine("A roof that opens up.");
}
}
class Minivan : Car
{
//重写方法将替换基类中的执行代码,即使这是通过基类进行的,情况也是这样,维持着多态
//不论通过基类还是自身访问,调用的都是这个
//Minivan car3 = new Minivan();; cars[2] = new Minivan();//
public override void DescribeCar()
{
base.DescribeCar();
System.Console.WriteLine("Carries seven people.");
}
}
class program
{
public static void Main()
{
Car car1 = new Car();
car1.DescribeCar();
System.Console.WriteLine("----------");
ConvertibleCar car2 = new ConvertibleCar();
//输出了A roof that opens up + Four wheels and an engine
car2.DescribeCar();
System.Console.WriteLine("----------");
Minivan car3 = new Minivan();
car3.DescribeCar();
System.Console.WriteLine("----------");
Car[] cars = new Car[3];
cars[0] = new Car();
//只输出了A roof that opens up
cars[1] = new ConvertibleCar();
cars[2] = new Minivan();
foreach (Car vehicle in cars)
{
System.Console.WriteLine("Car object: " + vehicle.GetType());
vehicle.DescribeCar();
System.Console.WriteLine("----------");
}
}
}
七:abstract和virtual和interface的区别
1:Abstract方法只能在抽象类中声明,虚方法则不是。
Abstract方法必须在派生类中重写,而virtual则不必(可以override也可以不用override)
2:Abstract方法不能声明方法实体,
Abstract public void SD();
虚方法则可以
public virtual void sdf()
{
Console.WriteLine("A");
}
3.虚方法可以实现多态,而抽象方法不可以
案例说明:
public abstract class Book //基类
{
public Book() { }
public abstract void getPrice(); //抽象方法,不含主体
public virtual void getName() //虚方法,可覆盖
{
Console.WriteLine("this is a test:virtual getName()");
}
public virtual void getContent() //虚方法,可覆盖
{
Console.WriteLine("this is a test:virtual getContent()");
}
public void getDate() //一般方法,若在派生类中重写,须使用new关键字
{
Console.WriteLine("this is a test: void getDate()");
}
}
public class JavaBook:Book //子类
{
public override void getPrice() //实现抽象方法,必须实现
{
Console.WriteLine("this is a test:JavaBook override abstract getPrice()");
}
public override void getName() //覆盖原方法,不是必须的
{
Console.WriteLine("this is a test:JavaBook override virtual getName()");
}
}
public class test //启动类
{
public test()
{
JavaBook jbook=new JavaBook();
jbook.getPrice(); //将调用JavaBook中getPrice()
jbook.getName(); //将调用JavaBook中getName()
jbook.getContent(); //将调用Book中getContent()
jbook.getDate(); //将调用Book中getDate()
}
public static void Main()
{
test t=new test();
}
}
4:abstract,virtual在实现过程中需要用到new 和 override,而interface则不用