C#学习相关系列之abstract和virtual用法

简介: C#学习相关系列之abstract和virtual用法

一、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

  • override是派生类用来重写基类方法的。调用的派生类方法,如需调用基类方法用base关键字
  • override不能重写非虚方法或静态方法。
  • override重写必须用abstract、override、virtrual修饰的方法。

new

  • new 是派生类用来隐藏基类方法的,在派生类中看不到基类方法,但调用的还是基类的方法。
  • 如果在派生类中要隐藏基类方法而不用new关键字,编译时会出现一个警告,提示如果是要隐藏基类中的方法,请使用new关键字。
  • new可以隐藏基类中的普通方法也可以是虚方法。
  • 如果在派生类中用private来修饰new 方法,那么只在该派生类中隐藏了基类中的方法,在该派生类之外,相当于没有隐藏基类中的方法;
  • 如果在派生类中隐藏了基类中的方法,在该派生类的派生类中,将延续对该派生类对基类方法的隐藏。
  • 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()");
        }
    }


相关文章
|
25天前
|
Linux C# 开发者
Uno Platform 驱动的跨平台应用开发:从零开始的全方位资源指南与定制化学习路径规划,助您轻松上手并精通 C# 与 XAML 编程技巧,打造高效多端一致用户体验的移动与桌面应用程序
【9月更文挑战第8天】Uno Platform 的社区资源与学习路径推荐旨在为初学者和开发者提供全面指南,涵盖官方文档、GitHub 仓库及社区支持,助您掌握使用 C# 和 XAML 创建跨平台原生 UI 的技能。从官网入门教程到进阶技巧,再到活跃社区如 Discord,本指南带领您逐步深入了解 Uno Platform,并提供实用示例代码,帮助您在 Windows、iOS、Android、macOS、Linux 和 WebAssembly 等平台上高效开发。建议先熟悉 C# 和 XAML 基础,然后实践官方教程,研究 GitHub 示例项目,并积极参与社区讨论,不断提升技能。
35 2
|
5月前
|
C#
C#的基本语法结构学习
【5月更文挑战第17天】C#基础语法包括变量(如`int x = 10`)、常量(`const int MAX_VALUE = 100`)、运算符(如算术和比较运算符)、控制语句(if、for、while等)和函数声明(`int Add(int x, int y) { return x + y; }`)。这些构成C#程序的基本元素。
66 0
|
2月前
|
C# 索引
C#中的virtual和override关键字
C#中的virtual和override关键字
36 3
|
2月前
|
开发框架 .NET API
C#/.NET/.NET Core推荐学习书籍(24年8月更新)
C#/.NET/.NET Core推荐学习书籍(24年8月更新)
|
4月前
|
C#
技术经验分享:C#DUID的用法及取得整数的几个方法
技术经验分享:C#DUID的用法及取得整数的几个方法
61 1
|
3月前
|
Dart 算法 JavaScript
C#数据结构与算法入门教程,值得收藏学习!
C#数据结构与算法入门教程,值得收藏学习!
|
4月前
|
前端开发 Java C#
GitHub突破5k Star!这件事情我坚持了3年,努力打造C#/.NET/.NET Core全面的学习、工作、面试指南知识库
GitHub突破5k Star!这件事情我坚持了3年,努力打造C#/.NET/.NET Core全面的学习、工作、面试指南知识库
|
5月前
|
C#
C#的类和对象的概念学习案例刨析
【5月更文挑战第17天】C#是一种面向对象的语言,以类和对象为核心。类作为对象的模板,定义了属性(如Name, Age)和行为(如Greet)。对象是类的实例,可设置属性值。封装通过访问修饰符隐藏实现细节,如Customer类的私有name字段通过Name属性访问。继承允许新类(如Employee)从现有类(Person)继承并扩展。多态让不同对象(如Circle, Square)共享相同接口(Shape),实现抽象方法Area,提供灵活的代码设计。
63 1
|
5月前
|
开发框架 前端开发 .NET
C#编程与Web开发
【4月更文挑战第21天】本文探讨了C#在Web开发中的应用,包括使用ASP.NET框架、MVC模式、Web API和Entity Framework。C#作为.NET框架的主要语言,结合这些工具,能创建动态、高效的Web应用。实际案例涉及企业级应用、电子商务和社交媒体平台。尽管面临竞争和挑战,但C#在Web开发领域的前景将持续拓展。
168 3
|
5月前
|
SQL 开发框架 安全
C#编程与多线程处理
【4月更文挑战第21天】探索C#多线程处理,提升程序性能与响应性。了解C#中的Thread、Task类及Async/Await关键字,掌握线程同步与安全,实践并发计算、网络服务及UI优化。跟随未来发展趋势,利用C#打造高效应用。
181 3