泛型编程
一种编程范式,目标是编写 类型无关 的代码
将算法和数据结构被设计成可以处理多种数据类型,而不是针对特定类型进行硬编码。
允许使用相同的代码逻辑处理不同类型的数据,从而提高代码的复用性和可维护性。
各语言对泛型编程的支持
C++:
- 模板(函数模板和类模板)
Java:
-
泛型方法和泛型类
public static <T> T add(T a, T b)
//JAVA 泛型方法的基本介绍
//1)public
与 返回值T
中间<T>
非常重要,可以理解为声明此方法为泛型方法。
//2) 只有声明了的方法才是泛型方法,泛型类中使用了泛型的成员方法并不是泛型方法。
//3) 表明该方法将使用泛型类型T
,此时才可以在方法中使用泛型类型T
。
//4) JAVA的泛型方法不能直接用于基本类型。
特化模板
从面向对象的角度来看,特化模板就相当于一个继承了通用模板的子类
C++ 的 类模板和函数模板,都支持模板特化
在语法层面,JAVA 没有 C++ 中模板特化的支持。但是依然可以通过继承和重载来模拟类似的效果。
当然,在实操中,JAVA开发人员进行泛型编程已属少见,更别说模拟C++特化模板。
况且,没有C++的知识,JAVA开发人员很可能没有特化模板的概念。
内部机制
JAVA 类型插除
类模板和泛型类的继承
C++ 中的实现
c++ 泛型编程有两种实现方式
- 模板
- 多态
一、模板
- 函数模板
- 类模板
二者均可以进行特化模板
代码示例
单个类型模板
注意 add(1,1.5);
//错误,无法推导出模板参数类型,这个跟java有差异。
#include <iostream>
using namespace std;
template <typename T>
T add(T a, T b) {
return a + b;
}
int main() {
int a = 1, b = 2;
double c = 1.5, d = 2.5;
int sum_int = add(a, b);//3 // 编译器生成 int 特化版本
double sum_double = add(c, d);//4 // 编译器生成 double 特化版本
// add(1,1.5);//错误,无法推导出模板参数类型,这个跟java有差异。
std::cout << "Sum int: " << sum_int << ", Sum double: " << sum_double << std::endl;
}
错误的JAVA写法
函数的申明没有问题,错误在于函数体中的a+b
因为Java泛型不支持基本类型,且+
只能在基本类型中使用。因此,这种写法表示对两个类进行+
运算,错误。
public static <T> T add(T a, T b) {
return a+b;//错误
}
正确
允许 add(1.1, 2);
这个与C++有差异,因为这里的T
都是Number
的子类
public class func {
public static void main(String[] args) {
System.out.println("Hello World!");
System.out.println(add(1, 2));//3.0
System.out.println(add(1.1, 2.2));//3.3000000000000003
System.out.println(add(1.1, 2));//3.1
System.out.println(add(1, 2.2));//3.2
}
public static <T extends Number> double add(T a, T b) {
return a.doubleValue() + b.doubleValue();
}
}
class template
#include <iostream>
using namespace std;
// 通用模板
template <typename T>
class MyContainer {
public:
MyContainer(T data) : data(data) {}
void printData() {
std::cout << "General template: " << data << std::endl;
}
private:
T data;
};
test class template
int main() {
MyContainer<int> int_container(42);
MyContainer<double> double_container(3.14);
int int_data = int_container.printData(); // 编译器生成 int 特化版本
double double_data = double_container.printData(); // 编译器生成 double 特化版本
}
func special template
template<typename T>
void print(T data) {
std::cout << "General function template: " << data << std::endl;
}
template<>
void print<bool>(bool data) {
std::cout << "Specialized function template for bool: " << (data ? "true" : "false") << std::endl;
}
class spcial template
template <>
class MyContainer<int> {
public:
MyContainer(int data) : data(data) {}
void printData() {
std::cout << "Specialized template for int: " << data << std::endl;
}
private:
int data;
};
test class special template 1
int main() {
MyContainer<int> int_container(42);
int_container.printData(); // 输出:Specialized template for int: 42
MyContainer<double> double_container(3.14);
double_container.printData(); // 输出:General template: 3.14
return 0;
}
多个类型参数
与上述类似,只是类型参数扩展为多个,这里以两个为例
func template
template<typename T, typename K>
void printData(T& data1, K& data2) {
std::cout << "Data 1: " << data1 << ", Data 2: " << data2 << std::endl;
}
class template
template<typename T, typename K>
class Pair {
public:
Pair(const T& first, const K& second) : first_(first), second_(second) {}
void print() const {
std::cout << "First: " << first_ << ", Second: " << second_ << std::endl;
}
private:
T first_;
K second_;
};
func special template
#include <iostream>
#include <string>
// 函数模板,接受两个不同类型的参数 T 和 K
template<typename T, typename K>
void printPair(const T& first, const K& second) {
std::cout << "General template: First: " << first << ", Second: " << second << std::endl;
}
// 函数模板重载,针对 T 和 K 都是 std::string 的情况
void printPair(const std::string& first, const std::string& second) {
std::cout << "Overloaded for std::string: First: " << first << ", Second: " << second << std::endl;
}
int main() {
int intValue = 42;
double doubleValue = 3.14;
std::string stringValue1 = "Hello";
std::string stringValue2 = "World!";
// 使用函数模板,处理 int 和 double 类型参数
printPair(intValue, doubleValue);
// 使用函数模板,处理 int 和 std::string 类型参数
printPair(intValue, stringValue1);
// 使用重载的函数模板,处理 std::string 和 std::string 类型参数
printPair(stringValue1, stringValue2);
return 0;
}
class special template
#include <iostream>
template<typename T, typename K>
class Pair {
public:
Pair(const T& first, const K& second) : first_(first), second_(second) {}
void print() const {
std::cout << "First: " << first_ << ", Second: " << second_ << std::endl;
}
private:
T first_;
K second_;
};
// 特化 Pair 类模板,针对 T 为 int 和 K 为 std::string 的情况
template<>
class Pair<int, std::string> {
public:
Pair(const int& first, const std::string& second) : first_(first), second_(second) {}
void print() const {
std::cout << "Specialized First: " << first_ << ", Specialized Second: " << second_ << std::endl;
}
private:
int first_;
std::string second_;
};
int main() {
int intValue = 42;
double doubleValue = 3.14;
std::string stringValue = "Hello, world!";
// 使用类模板,创建一个 int 和 double 类型参数的对象
Pair<int, double> intDoublePair(intValue, doubleValue);
intDoublePair.print();
// 使用特化的类模板,创建一个 int 和 std::string 类型参数的对象
Pair<int, std::string> intStringPair(intValue, stringValue);
intStringPair.print(); // 将调用特化的 print 函数
// 使用类模板,创建一个 double 和 std::string 类型参数的对象
Pair<double, std::string> doubleStringPair(doubleValue, stringValue);
doubleStringPair.print();
return 0;
}
特化模板
仅C++