一、abstract抽象类用法
1、抽象类的用途
一个类设计的目的是用来被其他类继承的,它代表一类对象的所具有的公共属性或方法,那么这个类就应该设置为抽象类。
抽象类是一种特殊的类,它不能被实例化,只能作为基类来派生出其它的具体类。抽象类使用abstract关键字来声明,其中可以包含抽象方法、虚方法、常规方法和属性。抽象类的主要作用是为其派生类提供一个通用的抽象基类。
抽象方法是一种没有实现的方法,它只有定义并且声明,没有具体实现。抽象方法使用abstract关键字来声明,在抽象类中定义,而其具体实现必须在派生类中实现。抽象方法的主要作用是为其派生类提供一个统一的方法接口。
抽象类的使用场景:
- 在类库中定义通用的抽象类作为基类,派生出具体的子类,可以提高代码的复用性,避免代码重复。
- 在多态的环境下,使用抽象类和抽象方法定义统一的虚方法,可以让子类实现这些方法,减少繁琐的类型转换操作。
- 抽象类和抽象方法的特点
- 抽象类不能被实例化,只能用于派生具体类。
- 抽象类可以包含抽象方法、虚方法、常规方法和属性。
- 抽象方法必须在派生类中被实现,否则派生类也必须声明为抽象类。
- 抽象方法必须被声明为public,因为派生类必须可以访问它。
2、抽象类的使用要求
- abstract修饰符可用于类、方法、属性、索引和事件。
- abstract修饰符用于简单地概括一个不完整的内容(摘要)。常用于基类,由派生类来继承实现基类的抽象属性和方法。
- 抽象类是对具有相同行为和特征的抽象,抽象类中的成员不会指定具体细节,一般再其派生类中去实现具体内容。
- 在普通类前加上abstract修饰符即可标注为抽象类。 如果一个普通类中对其成员使用了abstract修饰符,则该类必须修饰为抽象类。
- 无法使用sealed修饰符来修改抽象类,因为两个修饰符的含义相反。sealed修饰符阻止类被继承,而abstract修饰符要求类被继承。
- 继承抽象方法的派生类,必须实现override抽象类中的所有成员,用override重写来实现。
- 抽象类无法被实例化,但可以让派生类实例化。
- 抽象方法必须声明在抽象类中,声明抽象方法时,不能使用virtual、static、private修饰符。
- 抽象方法声明不提供实际的声明,因此没有方法主体,和接口类似,和虚方法不一样。
3、抽象类和接口的区别
相同点:
1、不能实例化;
2、包含未实现的方法声明
3、派生类必须实现未实现的方法,抽象类是抽象方法,接口则是所有成员(不仅是方法包括其他成员)
不同点:
1、接口可以多继承,抽象类不能实现多继承。
2、接口只能定义抽象规则,抽象类既能定义抽象规则也能提供已实现的成员。
3、接口是一组行为规范,抽象类是一个不完全的类,着重于族的概念。
4、接口支持回调,抽象类不能实现回调,因为继承不支持。
5、接口只包含方法、属性、索引器、事件的签名,但不能定义字段和包含实现的方法,抽象类可以定义属性、字段、包含有实现的方法。
6、接口可以作用于值类型和引用类型,抽象类只能作用于引用类型(例如:Struct只能继承接口)。
7、抽象类应主要用于关系密切的对象,而接口则是适合为不相关的类提供通用功能。
8、接口着重于Can—Do关系类型,抽象类则偏重于IS—A式关系。
9、接口多定义对象的行为,抽象类多定义对象的属性。
10、如果要设计小而简练的功能块,则使用接口,如果要设计大的功能单元,则使用抽象类。
11、接口对应是面向对象编程思想的重要原则:面向接口编程。
4、抽象类的示例
public abstract class Shape
{
public abstract double Area { get; }
}
public class Square : Shape
{
private double side;
public Square(double s)
{
side = s;
}
public override double Area
{
get { return side * side; }
}
}
abstract可以用来修饰类、方法、属性、索引器和事件,但不包括字段。使用abstract修饰的类,该类只能作为其他类的基类,不能实例化。而且abstract修饰的成员在派生类中必须全部实现,不允许部分实现,否则编译异常。
抽象类和抽象方法是C#编程中的两个重要概念,它们提供了面向对象编程的许多特性。通过抽象类和抽象方法,我们可以定义通用的属性和行为,然后让具体的子类来继承并实现它们。这样可以提高代码的复用性、可维护性和可扩展性,从而使我们的应用程序更加灵活和可维护。
二、virtual虚函数的用法
1、 虚函数的作用
当有一个定义在类中的函数需要在继承类中实现时,可以使用虚方法,虚方法是使用关键字virtual
声明的,虚方法可以在不同的继承类中有不同的实现,即为基类中定义的允许在派生类中重写的方法;
定义如下:
访问修饰符 virtual 函数返回类型 函数名(参数表) {函数体};
class Person
{
public virtual void XXX()//虚方法
{
Console.WriteLine("我有一个梦想,那就是动身去往远方!!");
}
}
class Boy : Person//继承person
{
public override void XXX()//虚方法调用
{
base.XXX();
}
}
调用上,使用子类构造的对象调用虚方法,就会调用子类的方法,使用父类构造的对象,就会调用父类的方法;在基类中声明的虚方法一般在派生类中对其进行调用,会运用到base
关键字:
2、虚函数的使用要求
1、 虚拟类其实指的是正常类中的虚拟方法,所以虚拟类可以直接使用实例,这是与抽象类不同的一点;
2、 虚拟方法是在方法前加virtual关键字,对方法进行声明,说明这个方法为虚方法;
3、虚拟函数和正常函数无区别;
4、子类继承虚拟类可以实现虚拟方法也可以不实现虚拟方法;
5、虚方法可以在不同的继承类中有不同的实现;
6、虚方法可以在不同的继承类中有不同的实现;
3、虚函数使用示例
public class Animal
{
public virtual void Speak()
{
Console.WriteLine("Animal speaks.");
}
}
public class Dog : Animal
{
public override void Speak()
{
Console.WriteLine("Dog barks.");
}
}
1.允许 子类 / 派生类 进行重写;
2.增加代码的可维护性,脉络较清淅有条理;
三、override和new的使用
override
new
代码1:
public class Program
{
static void Main(string[] args)
{
A a;
B b = new B();
C c = new C();
b.Test();
a = b;
a.Test();
a = c;
a.Test();
D d = new D();
d.Test();
Console.ReadLine();
}
}
public class A
{
public virtual void Test()
{
Console.WriteLine("A Test()");
}
}
public class B : A
{
public new void Test()
{
Console.WriteLine("B Test()");
}
}
public class C : A
{
public override void Test()
{
Console.WriteLine("C Test()");
}
}
public class D : C
{
public override void Test()
{
Console.WriteLine("D Test()");
}
}
代码2:
public class Program
{
static void Main(string[] args)
{
A a = new A();
a.Test();
B b = new B();
b.Test();
A c = new B();
c.Test();
A d = new C();
d.Test();
Console.ReadLine();
}
}
public class A
{
public virtual void Test()
{
Console.WriteLine("A Test()");
}
}
public class B : A
{
private new void Test()
{
Console.WriteLine("b Test()");
}
}
public class C : B
{
public override void Test()
{
Console.WriteLine("C Test()");
}
}
参考文献:
浅谈C#中的抽象类(abstract)和接口(interface)_c# 抽象类和接口-CSDN博客
C#抽象类和抽象方法详解_naer_chongya的博客-CSDN博客
C#中虚方法(virtual)详解_c# virtual-CSDN博客
C#中Abstract和Virtual-CSDN博客
C#基础知识四之override和new的区别-CSDN博客