0 声明
本人对于virtual以及abstract的认识还有所不足,下文的某些言论可能认识不成熟。请大家理性看待。
1 virtural
1.1 virtual
virtural意为虚拟的。和override关键字配合实现面向对象中的重写,进而实现多态。只能应用于方法中。
namespace test;
public class Animal
{
public virtual void eat()
{
Console.WriteLine("animial eat");
}
}
namespace test;
public class Dog:Animal
{
public override void eat()
{
Console.WriteLine("dog eat");
}
}
namespace test;
public class Cat : Animal
{
public override void eat()
{
Console.WriteLine("cat eat");
}
}
public class Test
{
public static void Main()
{
Animial[] animal = new Animial[3];
animal[0] = new Animal();
animal[1] = new Dog();
animal[2] = new Cat();
for (int i = 1; i < 3; i++)
{
animal[i].eat();
}
}
}
输出:
animial eat
dog eat
cat eat
上面的例子是多态的一个展示——
- 通过将基类引用指向派生类对象
- 并调用重写的方法
一个方法展现出多种状态,即为多态。
1.2 与方法隐藏的区别
方法隐藏与重写的区别在于去掉了override,即派生类中有一个与基类中待重写方法一模一样的方法。这并不能实现多态。
上述例子中的输出会变成
输出:
animial eat
animal eat
animal eat
1.3 方法调用的原理
待续
2 abstract
abstract可以用于类和方法中。
与virtual关键字区别如下:
- abstract可以用于类中,意为抽象,有两层意思——第一,表示不可被实例化,因为没有实际用途(仅仅声明一个动物类,很难产生实际作用,需要派生类来实际产生作用;若有需要也可不声明为抽象类);第二,表示同类物体的共性。
- abstract还可用于abstract类中的方法。此时方法没有方法体,必须在派生类中重写。
- abstract中的正常方法:abstract类中的方法也可以不用abstract关键字修饰,如同正常方法一样,但只能被子类继承后调用。
- 总结2和3可得:abstract类中的方法,有些是没有差异的共性(3),有些是有差异的共性(2)。
如下是抽象的展示
namespace test;
public abstract class Animal
{
//动物吃饭的方式不尽相同,所以声明为抽象的,让派生类自己决定
public abstract void eat();
//从人的视角看,每个动物都有一个名字,所以Name属性不加abstract。
//为了保险起见(万一获取/设置动物的名字方式不同),可以加virtual以备重写
public string Name { get; set; }
public void NormalFunc()
{
Console.WriteLine("NormalFunc");
}
}
namespace test;
public class Cat : Animal
{
public override void eat()
{
Console.WriteLine("cat eat");
}
}
namespace test;
public class Dog:Animal
{
public override void eat()
{
Console.WriteLine("dog eat");
}
}
namespace test;
public class Test
{
public static void Main()
{
//错误,抽象类不可被实例化
//Animal animal = new Animal();
//声明一个引用是可以的
Animal[] animal = new Animal[3];
animal[1] = new Dog();
animal[2] = new Cat();
for (int i = 1; i < 3; i++)
{
animal[i].eat();
}
}
}