C++ Concept 和Java 接口

Concept及接口

我会用Java写个case来解释什么是C++的Concept。Concept可以理解为接口,它是一种广义的接口。不同于Java的Interface,通俗地讲,Java的Interface匹配于C++的纯虚类,但Concept这种接口更广泛一些——任何符合该Concept要求的类型都属于该Concept.事实上,我认为Java也有能力实现Concept的.

我们姑且称Concept为广义的,Interface是狭义的,你会看到这么称呼是有道理的。

狭义的 Printer接口

C++版的Printer接口:

class Printer
{
public:
virtual void print() = 0;
virtual ~Printer() = 0;
};

Java版的Printer接口:

interface Printer{
public void print();
}

这时一定有人跳出来说,不对,它们不一样。

是的,它们(C++纯虚类和Java interface)略有不同,但C++纯虚类和 Java abstract class也不一样。事实上:

  • C++纯虚类对应于Java interface

    • 你必须手动声明C++纯虚类的虚析构函数,否则在delete指向派生类的基类指针时不能够析构基类,事实上,纯虚类的析构函数也被声明为纯虚函数,如果你只派生一次,你忘记声明析构函数为虚函数也没关系,因为纯虚析构函数啥也不干——但这不是个Best Practice,因为谁也不敢保证纯虚类只派生一次而没有被多层继承;Java没有析构函数的概念。这点是不同的。
    • C++纯虚类有构造函数,而Java interface没有构造函数。
    • C++纯虚类可以有成员变量(不推荐),而Java interface不可以有。
  • C++虚类对应于Java抽象类
    • 如上(虚)析构函数的区别。
    • C++可以多重继承,Java抽象类只能被单继承。

上述思想可以说是面向对象语言的基础,无论C++、Java还是C#、python,只要是面向对象编程范式的语言,他们都有 运行时多态 这种功能。

为何分道扬镳?

事实上,C++并没有纯虚类这个概念,只有一个abstract class的概念,它包含纯虚类。在此 定义C++的纯虚类为只包含纯虚函数的类(除去默认生成的构造函数)

如你所见,在面向对象设计的时候,两种语言选择了不同的路。Java晚于C++出现,它吸取了C++的设计经验,抽象出一个类似纯虚类的概念即接口,用以描述一组类似的功能实现。Java是基于如下考虑才做这种设计的:

Java通过提出接口的概念、规定只许单继承,规避多重继承的复杂。多重继承的复杂是 C++主流思想不选择设计 类似Java标准库的这种 面向对象编程范式的库的重要原因。我们知道C++是个多范式语言,目前的主流是使用基于模板编程的范式设计标准库。

设想一情形:A、B、C是三个提供不同功能的纯虚类(接口),而类ab实现了A、B的功能,类bc实现了B、C的功能,现在有需求说要设计一个具有A、B、C功能的类,你可以:

  • 1、选择abc继承自ab、bc,重现实现B
  • 2、选择abc实现A、B、C接口

我不敢说哪一种是对错,无疑第二种方法更清晰明了,虽然要啰嗦一些。而如果你用的Java,你没有第一种方式可以选择。——当然,实际工作中你遇到的情形不可能这么傻,实际情况要复杂得多:ab和bc的B功能实现很可能不一样,而abc需要的B功能实现可能是ab或bc中的一种、或者完全是另一种B的实现,因此从软件工程的角度来说,你必须选择第二种实现。

广义的 Printer Concept

我们定义一种Printer Concept,所有具有如下要求的类型都属于该Concept:

  • 具有参数为空的 default constructor。
  • 具有一个参数为空的print成员函数(方法).

下面二者最重要的区别: C++ Concept把错误提前到了编译期,而Java版的Concept错误在运行期。

C++版Printer Concept:

C++的Concept是基于模板范式的 编译期多态 .

#include <iostream>
#include <cstdlib> class ChinesePrinter
{
public:
void print()
{
std::cout << "你好\n";
}
}; class EnglishPrinter
{
public:
void print()
{
std::cout << "hello\n";
}
}; template <typename Printer>
class PrinterUser
{
public:
void action ( Printer p )
{
p.print();
}
void action()
{
Printer p{};
p.print();
}
}; int main()
{
{
ChinesePrinter cp{};
PrinterUser<ChinesePrinter> cpu{};
cpu.action ();
}
{
EnglishPrinter cp{};
PrinterUser<EnglishPrinter> epu{};
epu.action ();
}
system("pause");
}

Java版Printer Concept:

虽然我们可以通过实现InvocationHandler接口得到一个更通用的Concept,但无论如何这都是一个玩具。我们先不论这个Concept对于Java有什么意义,但无疑Concept的提出对于C++是十分重要的。

package org.go;

import java.lang.reflect.Method;

public class PrinterUser {
Class Printer_ = null;
public PrinterUser(Class Printer) {
Printer_ = Printer;
} public static void main(String[] args) {
{
PrinterUser cpu = new PrinterUser(ChinesePrinter.class);
cpu.action();
}
{
PrinterUser epu = new PrinterUser(EnglishPrinter.class);
epu.action();
}
} public void action() {
Concept c = new Concept("print");
c.call(Printer_);
}
} class ChinesePrinter {
public void print() {
System.out.println("你好");
}
} class EnglishPrinter {
public void print() {
System.out.println("hello");
}
} class Concept {
private String conceptName_; public Concept(String conceptName) {
conceptName_ = conceptName;
} public void call(Object printConcept) {
try {
Method printMethod = printConcept.getClass().getMethod(conceptName_, null);
printMethod.invoke(printConcept, null);
} catch (Exception e) {
e.printStackTrace();
}
} public void call(Class clz) {
try {
Method printMethod = clz.getMethod(conceptName_, null);
printMethod.invoke(clz.newInstance(), null);
} catch (Exception e) {
e.printStackTrace();
}
}
}

狭义的 接口实现 与广义的Concept对比

假如我们还有这样一个接口:

C++:

class Screen
{
public:
virtual void print() = 0;
virtual ~Screen() = 0;
};

Java:

interface Screen{
public void print();
}

无论是Java还是C++,上述的Screen和Printer接口(纯虚类) 都符合 我们提出的Printer Concept。Concept是更高的一层抽象。是的没有错:类型是一类数据结构的抽象,接口是类型的抽象,Concept是接口的抽象。由此可见,interface对Java有多重要,Concept对C++就有多重要——或者说,接口对于编程有多么重要,Concept对C++就有多重要。

C++ Concept 和Java 接口的更多相关文章

  1. java接口调用——webservice就是一个RPC而已

    很多新手一听到接口就蒙逼,不知道接口是什么!其实接口就是RPC,通过远程访问别的程序提供的方法,然后获得该方法执行的接口,而不需要在本地执行该方法.就是本地方法调用的升级版而已,我明天会上一篇如何通过 ...

  2. java 接口的作用和好处

    1.java 接口的作用 http://blog.csdn.net/hack_bug/article/details/7634737 2.一位Java大牛的回答 很多JAVA初级程序员对于接口存在的意 ...

  3. java接口

    一.定义 Java接口(Interface),是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为( ...

  4. java接口的嵌套

    java接口 1.接口中定义的变量默认是public static final 型,且必须给其初值,所以实现类中不能重新定义,也不能改变其值 2.接口中的方法默认都是 public abstract ...

  5. java 接口和抽象类的区别

    java 接口和抽象类的区别抽象类:1.含有抽象方法的类一定为抽象类,反过来抽象类,不一定含有抽象方法:2.抽象类必须用abstract来进行定义,抽象方法也必须用abstract来进行定义:3.抽象 ...

  6. java 接口(上)

    1.接口中的方法都是抽象方法.而普通的抽象类里面不一定都是抽象方法.抽象类中必须有抽象方法,同时也可以有非抽象方法.继承抽象父类的子类中,如果依然有抽象方法,那么这个子类也是抽象类.即只要类中有抽象方 ...

  7. java接口和抽象类

    关于接口 1.创建一个接口,需要使用interface关键字. 2.实现一个接口,需要使用implements关键字. 3.接口的成员属性都是静态常量(默认public static final). ...

  8. python面向对象进阶 反射 单例模式 以及python实现类似java接口功能

    本篇将详细介绍Python 类的成员.成员修饰符.类的特殊成员. 类的成员 类的成员可以分为三大类:字段.方法和特性. 注:所有成员中,只有普通字段的内容保存对象中,即:根据此类创建了多少对象,在内存 ...

  9. 初探设计:Java接口和抽象类何时用?怎么用?

    今天犯了个错: “接口变动,伤筋动骨,除非你确定只有你一个人在用”.哪怕只是throw了一个新的Exception.哈哈,这是我犯的错误. 一.接口和抽象类 类,即一个对象. 先抽象类,就是抽象出类的 ...

随机推荐

  1. 简单聊聊不可或缺的Nginx反向代理服务器--实现负载均衡【上篇】

    今天又是新的一周,我养足了精神去对待新一周的工作,但是今天到公司发现还是有一点空闲时间的,所以就想与之前接触过的Nginx再交往得更深一点儿. 什么是Nginx: Nginx是一款高性能的http服务 ...

  2. [COGS 0014][网络流24题] 搭配飞行员

    先贴题面 14. [网络流24题] 搭配飞行员 ★★☆   输入文件:flyer.in   输出文件:flyer.out简单对比时间限制:1 s   内存限制:128 MB [问题描述]     飞行 ...

  3. ASP.NET Core 源码学习之 Logging[2]:Configure

    在上一章中,我们对 ASP.NET Logging 系统做了一个整体的介绍,而在本章中则开始从最基本的配置开始,逐步深入到源码当中去. 默认配置 在 ASP.NET Core 2.0 中,对默认配置做 ...

  4. JavaScript addEventListener 第三个参数

    先看一个完整的演示页面代码. Code <!DOCTYPE html> <html lang="zh-CN"> <head> <meta ...

  5. Python中的可变对象和不可变对象

    Python中的可变对象和不可变对象 什么是可变/不可变对象 不可变对象,该对象所指向的内存中的值不能被改变.当改变某个变量时候,由于其所指的值不能被改变,相当于把原来的值复制一份后再改变,这会开辟一 ...

  6. [补档][Poi2010]Monotonicity 2

    [Poi2010]Monotonicity 2 题目 给出N个正整数a[1..N],再给出K个关系符号(>.<或=)s[1..k]. 选出一个长度为L的子序列(不要求连续),要求这个子序列 ...

  7. iOS设置状态栏样式

    iOS设置状态栏样式可以使用两种方式. 方式一: 直接在需要改变默认状态栏样式的控制器中实现一个方法(其他任何事情都不用做): // 返回状态栏的样式 - (UIStatusBarStyle)pref ...

  8. kafka在windows下的安装和配置

    博主最近在学习有关kafka的配置安装以及在spring的集成使用.但网上关于kafka的配置参考资料基本都是于linux下的配置,于是博主在整理了相关windows下kafka的配置记录在博客里.由 ...

  9. javaweb 登陆注册页面

    视图的数据修改,表中也修改引用工具类用<%@ page import=""%> <%@ page import="java.util.Date" ...

  10. CentOS 7 服务器配置--安装Ftp

    #安装vsftp yum install -y vsftpd #将 /etc/vsftpd/user_list文件和/etc/vsftpd/ftpusers文件中的root这一行注释掉 #root # ...