浅谈C# 抽象类与开闭原则
作者:安静点-- 发布时间:2023-11-07 11:00:08
1.抽象类与抽象方法:
(1)使用关键字abstract修饰的类,称为抽象类.
(2)抽象类只是用到一个类所具有的行为,不能单独通过创建对象来使用.使用new是错误的.可以通过派生类来实现其函数成员的具体逻辑。
(3)抽象类中可以有抽象方法,也可以没有任何抽象方法.只要类中存在一个抽象方法,这个类就是抽象类。
(4)抽象类不能是静态的(static)或者密封的(sealed)
下面就是一个简单的抽象类
abstract class Vehicle
{
public abstract void test();
public void VehicleTest()
{
}
}
class Car : Vehicle
{
public override void test()
{
}
}
2.开闭原则
如果不是为了修改bug,或者是添加新的功能,不要随便更改类的代码。
换句话说,我们应该封装那些确定的,不变的,稳定的,固定的。把不确定的,有可能会改变的成员声明为抽象类,留给子类去实现。
3.我们简单实现了一个继承
class Program
{
static void Main(string[] args)
{
Vehicle raceCar = new RaceCar();
Console.ReadKey();
}
}
/// <summary>
/// 交通工具类
/// </summary>
class Vehicle
{
/// <summary>
/// 停车
/// </summary>
public void Stop()
{
Console.WriteLine("Stopped");
}
/// <summary>
/// 加油
/// </summary>
public void Fill()
{
Console.WriteLine("Fill");
}
}
class Car : Vehicle
{
public void Run()
{
Console.WriteLine("Car is running");
}
}
class RaceCar : Car
{
public void Run()
{
Console.WriteLine("RaceCar is running");
}
}
从上面的代码我们可以看出这是一个继承链,其中Run方法是根据不同种类的车来区别的,所以我们如果想实现多态,比如 Vehicle raceCar = new RaceCar();此时raceCar 对象是调不到Run方法的,因为Vehicle类中没有这个方法,以前对于这种情况的解决方法是在Vehicle中加上Run方法,并且判断有什么类型:
public void Run(string type)
{
if (type == "Car")
{
Console.WriteLine("Car is running");
}
else if (type == "RaceCar")
{
Console.WriteLine("RaceCar is running");
}
else
{
}
}
如上代码,这样的话,当增加新类型的时候还要再改这个基类中的方法,违反了开闭原则( 如果不是为了修改bug,或者是添加新的功能,不要随便更改类的代码),所以需要做一下修改:
public virtual void Run()
{
Console.WriteLine("RaceCar is running");
}
派生类来重写这个方法,这样增加新类型的时候重写就可以,就不用再更改基类的代码了。但是,如果你觉得这个类中基本不会调用这个Run方法,那我们可以去掉方法体,改成抽象方法,相应的类也变成抽象类,Run完全由派生类来重写。
class Program
{
static void Main(string[] args)
{
Vehicle raceCar = new RaceCar();
Console.ReadKey();
}
}
/// <summary>
/// 交通工具类
/// </summary>
abstract class Vehicle
{
/// <summary>
/// 停车
/// </summary>
public void Stop()
{
Console.WriteLine("Stopped");
}
/// <summary>
/// 加油
/// </summary>
public void Fill()
{
Console.WriteLine("Fill");
}
public abstractvoid Run()
{
Console.WriteLine("RaceCar is running");
}
}
class Car : Vehicle
{
public override void Run()
{
Console.WriteLine("Car is running");
}
}
class RaceCar : Car
{
public override void Run()
{
Console.WriteLine("RaceCar is running");
}
}
4.接口与抽象类
(1)具体类-》抽象类-》接口,越来越抽象,内部实现的类越来越少。
(2)抽象类为复用而生:专门作为基类来使用,也具有解耦功能。
(3)封装确定,开放不确定的,推迟到子类实现。
(4)接口为解耦而生,高内聚,低耦合,方便单元测试。
(5)都不能实例化,只能声明变量,引用具体类的实例。
来源:https://www.cnblogs.com/anjingdian/p/13138430.html
猜你喜欢
- 微信登录的实现与qq登录类似。不过微信登录比较麻烦,需要拿到开发者资质认证,花300块钱,然后应用的话还得有官网之类的,就是比较繁琐的前期准
- 打包与运行在项目开发完成之后,可以直接用IDEA将其打包成JAR包运行,也可以打包成WAR包运行以便在多服务器、多配置环境下运行。双击cle
- 网上很多资料在描述Java内存模型的时候,都会介绍有一个主存,然后每个工作线程有自己的工作内存。数据在主存中会有一份,在工作内存中也有一份。
- 前篇回顾:Spring源码解析容器初始化构造方法在上一篇文章中,我们介绍完了AnnotationConfigApplicationConte
- 主要介绍springboot项目中配置文件的加密前言为了保证服务器相关信息的保密,一般会采用加密的方式进行对配置文件原文的加密,今天介绍下s
- 一、Thread.start()与Thread.run()的区别通过调用Thread类的start()方法来启动一个线程,这时此线程是处于就
- package com.jjinfo.common.util; import java.util.Arrays; import java.u
- centos下搭建GitLab+Jenkins持续集成环境,供大家参考,具体内容如下1、安装JDKyum install -y java2、
- 这篇文章主要介绍了Java String的intern用法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,
- 分页查询分页查询将数据库中庞大的数据分段显示,每页显示用户自定义的行数,提高用户体验度,最主要的是如果一次性从服务器磁盘中读出全部数据到内存
- dart 是一个面向对象的语言;面向对象有继承封装多态dart的所有东西都是对象,所有的对象都是继承与object类一个类通常是由属性和方法
- * 的工作原理如图 * 是由每一个action请求(request)都包装在一系列的 * 的内部,通过redirectAction再一次
- 收费版本:Rainbow Brackets免费版本:Rainbow Brackets Lite介绍一款可以将 (圆括号) [方括号] {花括
- 本文首先将会回顾Spring 5之前的SpringMVC异常处理机制,然后主要讲解Spring Boot 2 Webflux的全局异常处理机
- 一、多表联合分页查询1.多表联合查询结果集建议使用VO类,当然也可以使用resultMappackage com.cjhx.tzld.ent
- 自动注入和@Autowire@Autowire不属于自动注入!注入方式(重要)在Spring官网上(文档),定义了在Spring中的注入方式
- 介绍Java桥梁模式(也称桥接模式)(Bridge Pattern)是一种设计模式,它将抽象和实现分离,使它们可以独立地变化.它通过一个大类
- 我就废话不多说了,大家还是直接看代码吧~<!-- 查询物品的id --><select id="checkIte
- 要求:如下图,使用线程操作 1、实时显示当前时间 2、输入加数和被加数,自动出现结果 分析:两个问题解决的方式一致,使用子线程进
- 1. 函数式接口的理解根据重构的思想,需要把容易变化的模块进行抽象并封装起来,从这个点来看,Java8新引入的函数式接口就是基于这个思想进行