接口和抽象类:如何使用普通类模拟接口和抽象类
目录
1.引言
2.抽象类和接口的定义与区别
3.抽象类和接口存在的意义
4.模拟实现抽象类和接口
5.抽象类和接口的应用场景
1.引言
在面向对象编程中,抽象类和接口是两个经常被提及的语法概念,也是面向对象编程的四大特性,以及很多设计模式和设计原则编程实现的基础。例如,我们可以使用接口实现面向对象的抽象特性、多态特性和基于接口而非实现的设计原则,使用抽象类实现面向对象的继承特性和模板设计模式,等等。
不过,并不是所有的面向对象编程语言都支持这两个语法概念,如C++这种编程语言只支持抽象类,不支持接口;而像 Python 这样的动态编程语言,既不支持抽象类,又不支持接口。尽管有些编程语言没有提供现成的语法来支持接口和抽象类,但是我们仍然可以通过一些手段模拟实现这两个语法概念。
这两个语法概念不但在工作中经常会被用到,而且在面试中经常被提及。接口和抽象类的区别是什么?什么时候使用接口?什么时候使用抽象类?抽象类和接口存在的意义是什么?通过阅读本节内容,相信读者可以从中找到答案。
2.抽象类和接口的定义与区别
不同的编程语言对接口和抽象类的定义方式可能有差别,但差别并不会很大。因为Java既支持抽象类,又支持接口,所以我们使用Java进行举例讲解,以便读者对这两个有直观的认识。
首先,我们看一下如何在 Java 中定义抽象类。
下面这段代码是一个典型的抽象类使用场景(模板设计模式)。Logger 是一个记录日志抽象类,FileLogger 类和 MessageQueueLogger 类继承 Logger 类,分别实现不同的日志记式:将日志输出到文件中和将日志输出到消息队列中。FileLogger和MessageQueueLogger 两个子类复用了父类 Logger 中的 name、enabled、minPermittedLevel 属性,以及log()方法,因为这两个子类输出日志的方式不同,所以它们又各自重写了父类中的 doLog()方法。
public abstract class Logger{private String name;private boolean enabled;private evel minPermittedLevel;public Logger(String name, boolean enabled, Level minPermittedLevel){this.name = name;this.enabled = enabled;this.minPermittedLevel = minPermittedLevel;}public void log(Level level,String message){boolean loggable = enabled && (minPermittedLevel.intValue()<=level.intValve());if(!loggable) return;doLog(level,message);}protected abstract void doLog (Level level,String message);
}//抽象类的子类:输出日志到文件
public class FileLogger extends Logger{private Writer fileWriter;public FileLogger(String name,boolean enabled.Ievel minPermittedLevel,String filepath){super(name,enabled,minPermittedLevel);this.fileWriter = new FileWriter(filepath);}@0verridepublic void doLog(Level level,string mesage){//格式化leve1和message,并输出到日志文件fileWriter.write(...);}
}//抽象类的子类:输出日志到消息中间件(如Kafka)
public class MessageQueueLogger extends Logger{private MessageQueueClient msgQueueclient;public MessageQueueLogger(String name, boolean enabled,Level minPermittedLevel,MessageQueueClient msgQueueClient){super(name,enabled,minPermittedLevel);this.msgQueueClient = msgQueueClient;}@Overrideprotected void doLog(Level level,String mesage){//格式化1evel和message,并输出到消息中间件msgQueueClient.send(...);}
}
结合上述示例,我们总结了下列抽象类的特点:
1)抽象类不允许被实例化,只能被继承。也就是说,我们不能通过关键字 new定义一个
抽象类的对象(编写“Logger logger=new Logger(..);”语句会报编译错误)。
2)抽象类可以包含属性和方法。方法可以包含代码实现(如Logger类中的log()方法)也可以不包含代码实现(如Logger 类中的 doLog()方法)。不包含代码实现的方法称为抽象方法。
3)子类继承抽象类时,必须实现抽象类中的所有抽象方法。对应到示例代码中,所有继承Logger 抽象类的子类都必须重写 doLog()方法。
上面是对抽象类的定义。接下来,我们看一下如何在Java 中定义接口。我们还是先看一段示例代码。
public interface Filter {void doFilter(RpcRequest req)throws RpcException;
}//接口实现类:鉴权过滤器
public class AuthencationFilter implements Filter {@Overridepublic void doFilter(RpcRequest req)throws RpcException {//省略鉴权逻辑...}
}//接口实现类:限流过滤器
public class RatelimitFilter implements Filter {@Overridepublic void doFilter(RpcRequest req) throws RpcException {//...省略限流逻辑}
}//过滤器使用示例
public class Application {private list<Filter> filters = new ArrayList<>();public Application(){filters.add(new AuthencationFilter());filters.add(new RatelimitFilter());public void handleRpcRequest(RpcRequest req){try{for(Filter filter : filters ){filter.doFilter(req);}}catch(RpcException e){//..省略处理过滤结果.}}//..省略其他处理逻辑.}
}
上述代码是一个典型的接口使用场景。通过Java 中的 interface 关键字,我们定义了一个Filter 接口。AuthencationFilter 和RateLimitFiliter是接口的两个实现类,分别实现了对RPC求鉴权和限流。结合上述代码,我们总结了下列接口的特点:
1)接口不能包含属性(也就是成员变量)。
2)接口只能声明方法,方法不能包含代码实现。
3)类实现接口时,必须实现接口中声明的所有方法。
有些读者可能说,在Java 1.8版本之后,接口中的方法可以包含代码实现,并且接口可以包含静态成员变量。注意,这只不过是Java语言对接口定义的妥协,目的是方便使用。抛开Java 这一具体的编程语言,接口仍然具有上述3个特点。
在上文中,我们介绍了抽象类和接口的定义,以及各自的语法特性。从语法特性方面对比,抽象类和接口有较大的区别,如抽象类中可以定义属性、方法的实现,而接口中不能定义属性,方法也不能包含代码实现,等等。除语法特性以外,从设计的角度对比,二者也有较大的区别。
抽象类也属于类,只不过是一种特殊的类,这种类不能被实例化为对象,只能被子类继承。我们知道,继承关系是一种is-a关系,那么,抽象类既然属于类,也表示一种is-a关系。相比抽象类的is-a关系,接口表示一种has-a关系(或can-do关系、behave like 关系),表示具有某些功能。因此,接口有一个形象的叫法:协议(contract)。
3.抽象类和接口存在的意义
在上面我们介绍了抽象类和接口的定义与区别,现在我们探讨一下抽象类和接口存在的意义,以便读者知其然,知其所以然。
为什么需要抽象类?它能够在编程中解决什么问题?在上面我们讲到,抽象类不能被实例化,只能被继承。之前,我们还讲过,继承能够解决代码复用问题。因此,抽象类是为代码复用而生的。多个子类可以继承抽象类中定义的属性和方法,这样可以避免在子类中重复编写相同的代码。
既然继承就能达到代码复用的目的,而维承并不要求父类必须是抽象类,那么,不使用抽象类照样可以实现继承和复用。从这个角度来看,抽象类语法似乎是多余的。那么,除解决代码复用问题以外,抽象类还有其他存在的意义吗?
我们还是结合之前打印日志的示例代码进行讲解。不过,我们需要先对之前的代码进行改造。在改造之后,Logger不再是独象类。万法一个普通类。另外,我们删除了Logger类中的log()、doLog()方法,新增了isLoggable()方法,FileLogger类和 MessageQueueLogger 类仍级继承 Logger 类。具体代码如下:
//父类:Logger, 非抽象类就是普通类,删除了log()和doLog()方法,新增了 isLoggeable()方法
public abstract class Logger{private String name;private boolean enabled;private evel minPermittedLevel;public Logger(String name, boolean enabled, Level minPermittedLevel){this.name = name;this.enabled = enabled;this.minPermittedLevel = minPermittedLevel;}protected boolean isLoggable(){boolean loggable = enabled && (minPermittedLevel.intValue()<=level.intValve());return loggable;}
}//抽象类的子类:输出日志到文件
public class FileLogger extends Logger{private Writer fileWriter;public FileLogger(String name,boolean enabled.Ievel minPermittedLevel,String filepath){super(name,enabled,minPermittedLevel);this.fileWriter = new FileWriter(filepath);}@0verridepublic void log(Level level,string mesage){if (!isLoggable())return;fileWriter.write(...);}
}//抽象类的子类:输出日志到消息中间件(如Kafka)
public class MessageQueueLogger extends Logger{private MessageQueueClient msgQueueclient;public MessageQueueLogger(String name, boolean enabled,Level minPermittedLevel,MessageQueueClient msgQueueClient){super(name,enabled,minPermittedLevel);this.msgQueueClient = msgQueueClient;}@Overridepublic void log(Level level,string mesage){if (!isLoggable())return;msgQueueClient.send(...);}
}
虽然上面这段代码的设计思路达到了代码复用的目的,但是无法使用多态特性。如果我们像下面这样编写代码,就会出现编译错误,因为Logger类中并没有定义log()方法。
Logger logger = new FileLogger("access-log",true, Level.WARN, "/users/wangzheng/access.log") ;
logger.log(Level,ERROR, "This is a test log message .");
读者可能会说,这个问题的解决很简单,在Logger类中,定义一个空的log()方法,让子类重写 Logger类的log()方法,并实现自己的日志输出逻辑,不就可以了吗?代码如下所示。
Public class Logger{//...省略部分代码...Public void log(Level level,string mesage){ //方法体为空}
}public class FileLogger extends Logger{//..省略部分代码..@Overridepublic void log(Level level,String mesage){if(!isLoggable())return;//格式化1evel和message,并输出到日志文件filewriter.write(...);}
}public class MessageQueuelogger extends Logger{//..省略部分代码..@Overridepublic void log(Level level, string mesage){if(!isLoggable())return;//格式化1evel和message,并输出到消息中间件msgQueueClient.send(...);}
}
虽然上面这段代码的设计思路可用,能够解决问题,但是,它显然没有之前基于抽象*。设计思路优雅,理由如下。
1)在Logger类中,定义一个空的方法,会影响代码的可读性。如果我们不熟悉Logger类背后的设计思想,加之代码的注释不详细,那么,在阅读Logger类的代码时,有可解生为什么定义一个空的log()方法的疑问。或许,我们需要通过查看Logger、FileLogger和MessageQueueLogger 之间的继承关系,才能明白其背后的设计意图。
2)当创建一个新的子类并继承Logger类时,我们很有可能忘记重新实现log()方法。前基于抽象类的设计思路,编译器会强制要求子类重写log()方法,否则会报编译错误。读者可能会问,既然要定义一个新的Logger 类的子类,那么怎么会忘记重新实现 log()方法呢?其实,我们举的例子比较简单,Logger类中的方法不多,代码行数也很少。我们可以想象一下如果Logger类中有几百行代码,包含很多方法,除非我们对Logger类的设计非常熟悉,否则极有可能忘记重新实现log()方法。
3)Logger类可以被实例化,换句话说,我们可以通过关键字new定义一个Logger 类的对象,并且调用它的空的log()方法。这增加了类被误用的风险。当然,这个问题可以通过设置私有的构造函数的方式来解决。不过,这显然没有基于抽象类的实现思路优雅。为什么需要接口?它能够在编程中解决什么问题?抽象类侧重代码复用,而接口侧重解耦。接口是对行为的一种抽象,相当于一组协议或契约,读者可以类比API。调用者只需要关注抽象的接口,不需要了解具体的实现,具体的实对调用者透明。接口实现了约定和实现分离,可以降低代码的耦合度,提高代码的可扩展性。
4.模拟实现抽象类和接口
有些编程语言只有抽象类,并没有接口,如C++。我们可以通过抽象类模拟接口,只要它满足接口的特性(接口中没有成员变量,只有方法声明,没有实现方法,实现接口的类必须实现接口中的所有方法)即可。在下面这段C++代码中,我们使用抽象类模拟了一个接口。
class Strategy{//用抽象类模拟接口public:virtual ~Strategy();virtual void algorithm() = 0,protected:Strategy();
}
抽象类 Strategy 没有定义任何属性,并且所有的方法都声明为virual(等同于 Java中的abstract 关键字)类型,这样,所有的方法都不能有代码实现,并且所有继承这个抽象类的子类都要实现这些方法。从语法特性上来看,这个抽象类就相当于一个接口。
不过,现在流行的动态编程语言,如Python、Ruby等,它们不但没有接口的概念,而且没有抽象类。在这种情况下,我们可以使用普通类模拟接口。具体的Java代码实现如下。
public class MockInterface{protected MockInterface();public void funcA(){throw new MethodUnSupportedException();}
}
我们知道,类中的方法必须包含实现,但这不符合接口的定义。其实,我们可以让类中的方法抛出 MethodUnSupportedException 异常来模拟不包含实现的接口,并且,在子类继承父类时,强迫子类主动实现父类的方法,否则会在运行时抛出异常。那么,如何避免这个类被实例化呢?我们只需要将构造函数设置成protected属性,这样就能避免非同一包(package)下的类去实例化 MockInterface。不过,这样做还是无法避免同一包下的类去实例化 MockInterface.为了解决这个问题,我们可以学习Google Guava中 @VisibleForTesting注解的做法,自定义个注解,人为地表明其不可实例化。
上面讲了如何用抽象类来模拟接口,以及如何用普通类来模拟接口,那么,如何用普通类来模拟抽象类呢?我们可以类比 MockInterface 类的处理方式,让本该为abstract的方法内部抛出MethodUnSupportedException异常,并且将构造函数设置为protected 属性,避免实例化。
5.抽象类和接口的应用场景
在真实的项目开发中,什么时候该用抽象类?什么时候该用接口?实际上,判断的标准很简单。如果我们要表示一种is-a关系,并且是为了解决代码复用的问题,那么使用抽象类;如果我们要表示一种 has-a关系,并且是为了解决抽象而非代码复用的问题,那么使用接口。
从类的继承层次上来看,抽象类是一种自下而上的设计思路,先有子类的代码重复,再抽象出上层的父类(也就是抽象类)。而接口正好相反,它是一种自上而下的设计思路。在编程开发时,一般先设计接口,再考虑具体的实现。
相关文章:
接口和抽象类:如何使用普通类模拟接口和抽象类
目录 1.引言 2.抽象类和接口的定义与区别 3.抽象类和接口存在的意义 4.模拟实现抽象类和接口 5.抽象类和接口的应用场景 1.引言 在面向对象编程中,抽象类和接口是两个经常被提及的语法概念,也是面向对象编程的四大特性,以及很多设计模式…...
【文档智能】实践:基于Yolo三行代码极简的训练一个版式分析模型
一、数据集 本文以开源的CDLA数据集做为实验,CDLA是一个中文文档版面分析数据集,面向中文文献类(论文)场景。包含以下10个label: 数据集下载地址:https://github.com/buptlihang/CDLA 数据集是labelme格式…...
聚观早报 | 深蓝G318价格发布;比亚迪方程豹豹3官图发布
聚观早报每日整理最值得关注的行业重点事件,帮助大家及时了解最新行业动态,每日读报,就读聚观365资讯简报。 整理丨Cutie 6月15日消息 深蓝G318价格发布 比亚迪方程豹豹3官图发布 夸克App升级高考AI搜索 iOS 18卫星通信实测 Redmi K70…...
如何实现内网穿透?快解析-免费内网穿透工具
在现如今的ipv4时代,随着上网电脑及其他智能设备越来越多,公网IP地址出现了枯竭的情况。近几年,内网穿透这个词被不断提及,这也是在无公网IP环境下实现异地访问的一种可行办法,下面我就给大家介绍一下内网穿透的原理。…...
【python-AI篇】人工智能技能树思维导图
大致总结一下得出如下思维导图,如不完善日后迭代更新 1. python基础三方库 1.1 科学计算库 ---- numpy库 1.2 科学计算库 ---- Scipy库 1.3 数据分析处理库 ---- pandas库 1.4 可视化库 ---- matplotlib库 1.5 可视化库 ---- seaborn库 1.6 机器学习和数据挖掘库 …...
Vue的computed大致细节
computed computed具体实现流程computer的执行顺序 computed 具体实现流程 computer内部首先是标准化参数然后调用runner函数进行依赖收集设置dirty为true创建副作用函数,具体如下 const runner effect(getter,{//延迟执行lazy:true,//标记为computed effect 用…...
第5章:模型预测控制(MPC)的代码实现
1. 建立 QP 模型: 1.1 车辆模型: 注:使用车辆横向动力学模型 纵向动力学模型(误差模型) 1.2 QP 问题模型: 注:详细推导见 笔记100:使用 OSQP-Eigen 对 MPC 进行求解的方法与代码-…...
论文学习day01
1.自我反思的检索增强生成(SELF-RAG) 1.文章出处: Chan, C., Xu, C., Yuan, R., Luo, H., Xue, W., Guo, Y., & Fu, J. (2024). RQ-RAG: Learning to Refine Queries for Retrieval Augmented Generation. ArXiv, abs/2404.00610. 2.摘…...
Github入门教程,适合新手学习(非常详细)
前言:本篇博客为手把手教学的 Github 代码管理教程,属于新手入门级别的难度。教程简单易操作,能够基本满足读者朋友日常项目寄托于 Github 平台上进行代码管理的需求。Git 与 Github 是一名合格程序员 coder 必定会接触到的工具与平台&#x…...
C# OpenCvSharp 代数运算-add、scaleAdd、addWeighted、subtract、absdiff、multiply、divide
在C#中使用OpenCvSharp进行图像处理时,理解和合理使用各种图像操作函数可以帮助我们实现许多实际应用中的需求。下面,我将详细介绍每个函数的使用,并给出与实际应用项目相关的示例,包括运算过程和运算结果。 1. add 函数 作用 将两幅图像进行相加,可以达到图像融合的目的…...
为什么说Python 是胶水语言?
"Python 是胶水语言"这一说法是指它很擅长将不同的程序或代码库连接在一起,能够让来自不同编程语言或框架的组件无缝协作。Python 具有丰富的库和简单的语法,使得它可以轻松调用其他语言编写的程序或使用不同技术栈的模块。 以下是几个…...
GitLab教程(二):快速上手Git
文章目录 1.将远端代码克隆到本地2.修改本地代码并提交到远程仓库3.Git命令总结git clonegit statusgit addgit commitgit pushgit log 首先,我在Gitlab上创建了一个远程仓库,用于演示使用Gitlab进行版本管理的完整流程: 1.将远端代码克隆到本…...
结构体知识点
基本概念 结构体是一种自定义变量类型,类似于枚举需要自己定义。 它是数据和函数的集合。 在结构体中,可以声明各种变量和方法。 基本语法 1.结构体一般写在namespace语句块中。 2.结构体关键字struct struct 自定义结构体名 {//第一部分//变量//…...
C# —— 显示转换
显示转换: 通过一些方法可以将其他数据类型转换为我们想要的数据类型 1.括号强转 作用: 一般情况下 将高精度的类型转换为低精度 // 语法: 变量类型 变量名 (转换的变量类型名称) 变量; // 注意: 精度问题 范围问题 sbyte sb 1; short s 1; int …...
zip加密txt文件后,暴力破解时会有多个解密密码可以打开的疑问??
最近在做一个关于zip压缩文件解密的测试,发现通过暴力解密时,会有多个解密密码可以打开,非常疑惑,这里做个问题,希望能有大佬解惑。 1、首先在本地创建一个113449.txt的文件,然后右键txt文件选择压缩&…...
css入门宝典
3.1.4 通配符选择器 语法 : *{} 作用 : 让页面中所有的标签执行该样式,通常用来清除间距 例子 : *{ margin: 0; //外间距 padding: 0; //内间距 } 一 CSS基本语法 1基础知识 1.1概述 Css (层叠样式表)是种格式化网页的标准方式, 用于控制设置网页的样式ÿ…...
【AI原理解析】— 星火大模型
目录 1. 模型基础架构 神经网络结构 编码器 解码器 多层神经网络结构 其他自然语言处理技术 2. 训练数据 来源 规模 3. 自监督学习 Masked Language Model (MLM) 4. 参数量与计算能力 大规模参数量 深度学习算法 5. 技术特点 多模态输入 自我学习与迭代 6. 应…...
StarNet实战:使用StarNet实现图像分类任务(一)
文章目录 摘要安装包安装timm 数据增强Cutout和MixupEMA项目结构计算mean和std生成数据集 摘要 https://arxiv.org/pdf/2403.19967 论文主要集中在介绍和分析一种新兴的学习范式——星操作(Star Operation),这是一种通过元素级乘法融合不同子…...
单链表——AcWing.826单链表
单链表 定义 单链表是一种常见的数据结构,它由一系列节点组成,每个节点包含一个数据元素和一个指向下一个节点的指针。 运用情况 用于实现动态的数据存储和管理,例如实现栈、队列等其他数据结构。在需要频繁进行插入和删除操作时非常有用…...
10:Hello, World!的大小
OpenJudge - 10:Hello, World!的大小 描述 还记得在上一章里,我们曾经输出过的“Hello, World!”吗? 它虽然不是本章所涉及的基本数据类型的数据,但我们同样可以用sizeof函数获得它所占用的空间大小。 请编程求出它的大小,看看跟你…...
【Pandas驯化-03】Pandas中常用统计函数mean、count、std、info使用
【Pandas驯化-03】Pandas中常用统计函数mean、count、std、info使用 本次修炼方法请往下查看 🌈 欢迎莅临我的个人主页 👈这里是我工作、学习、实践 IT领域、真诚分享 踩坑集合,智慧小天地! 🎇 相关内容文档获取 微…...
WordPress——Argon主题美化
文章目录 Argon主题美化插件类类别标签页面更新管理器文章头图URL查询监视器WordPress提供Markdown语法评论区头像设置发信设置隐藏登陆备份设置缓存插件 主题文件编辑器页脚显示在线人数备案信息(包含备案信息网站运行时间)banner下方小箭头滚动效果站点功能概览下方Links功能…...
Vue部分文件说明
1.eslintignore文件 Eslint会忽略的文件 # Eslint 会忽略的文件.DS_Store node_modules dist dist-ssr *.local .npmrc 2.gitignore # Git 会忽略的文件.DS_Store node_modules dist dist-ssr .eslintcache# Local env files *.local# Logs logs *.log npm-debug.log* yarn-de…...
图书管理系统(SpringBoot+SpringMVC+MyBatis)
目录 1.数据库表设计 2.引入MyBatis和MySQL驱动依赖 3.配置数据库&日志 4.Model创建 5.用户登录功能实现 6.实现添加图书功能 7.实现翻页功能 1.数据库表设计 数据库表是应⽤程序开发中的⼀个重要环节, 数据库表的设计往往会决定我们的应⽤需求是否能顺利实现, 甚至决…...
11.泛型、trait和生命周期(上)
标题 一、泛型数据的引入二、改写为泛型函数三、结构体/枚举中的泛型定义四、方法定义中的泛型 一、泛型数据的引入 下面是两个函数,分别用来取得整型和符号型vector中的最大值 use std::fs::File;fn get_max_float_value_from_vector(src: &[f64]) -> f64…...
UML与设计模式
1、关联关系 关联关系用于描述不同类的对象之间的结构关系,它在一段时间内将多个类的实例连接在一起。关联关系是一种静态关系,通常与运行状态无关,而是由“常识”、“规则”、“法律”等因素决定的,因此关联关系是一种强关联的关…...
如何在Spring Boot中实现图片上传至本地和阿里云OSS
在开发Web应用时,处理文件上传是常见的需求之一,尤其是在涉及到图片、视频等多媒体数据时。本文将详细介绍如何使用Spring Boot实现图片上传至本地服务器以及阿里云OSS存储服务,并提供完整的代码示例。 一、上传图片至本地 首先,…...
几个小创新模型,KAN组合网络(LSTM、GRU、Transformer)时间序列预测,python预测全家桶...
截止到本期,一共发了8篇关于机器学习预测全家桶Python代码的文章。参考往期文章如下: 1.终于来了!python机器学习预测全家桶 2.机器学习预测全家桶-Python,一次性搞定多/单特征输入,多/单步预测!最强模板&a…...
ubuntu18.04 配置 mid360并测试fast_lio
1.在买到Mid360之后,我们可以看到mid360延伸出来了三组线。 第一组线是电源线,包含了红色线正极,和黑色线负极。一般可以用来接9-27v的电源,推荐接12v的电源转换器,或者接14.4v的电源转换器。 第二组线是信号线&#x…...
基于Java的诊所医院管理系统,springboot+html,MySQL数据库,用户+医生+管理员三种身份,完美运行,有一万一千字论文
演示视频 基本介绍 基于Java的诊所医院管理系统,springboothtml,MySQL数据库,用户医生管理员三种身份,完美运行,有一万一千字论文。 用户:个人信息管理、预约医生、查看病例、查看公告、充值、支付费用...…...
做灯箱到哪个网站找业务/商务网站建设
在从数据库中读取数据时最好直接在select语句中加入选择条件,从而直接限制筛选出符合条件的数据,而不建议读出所有的数据然后用ABAP代码来过滤筛选。 例如,不建议使用: Select * from zflight. Check : zflight-airln ‘LF’ a…...
网站建设优化现状图表/小说推广平台有哪些
题意简概: 输入n个元素组成的序列S,你需要找一个乘积最大的连续子序列。如果这个最大的乘积不是正数,应输出0,表示无解。1<n<18,-10<Si<10。 Sample Input32 4 -352 5 -1 2 -1Sample OutputCase #1: The m…...
用php做网站用什么框架/搜索网站的软件
冒泡排序(Bubble Sort) 冒泡排序算法的运作如下: 1.比较相邻的元素。如果第一个比第二个大,就交换他们两个。 2.对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。 3.针对所有的…...
wordpress全站pjax/百度公司招聘信息
持续更新中。。。 尝试用蓝牙hid协议 文章目录1.个人实践1.1 app在后台处于没有被系统杀死时,可以自动重连和发数据1.2 但在后台被系统杀死(没有被收到杀死),当连接状态发生变化的时候,系统会唤醒app,扫描后会调用1.3 因为后台获取位置时&…...
wordpress更换百度编辑器/站长平台
关键词:学习力、生产力、笔记本软件、surface使用指南引入:在信息化迅速发展的今天,智能手机、计算机已经成为人们必不可少的工具。要想专注于办公学习,一个好的载体必不可少,所以本文集中讲一下我个人对于笔记本电脑或…...
深圳服务网站设计哪家公司好/推广平台哪个效果最好
题库来源:安全生产模拟考试一点通公众号小程序 2022化工自动化控制仪表题库系化工自动化控制仪表试卷新版教材大纲题库!2022年化工自动化控制仪表复训题库及在线模拟考试根据化工自动化控制仪表考试大纲。化工自动化控制仪表考试模拟题通过安全生产模拟…...