java - Java 泛型 - 关于大于对象的方法的快速问题
问题描述
我在 Java 课上有一个作业,我们正在学习泛型,我查看了我的笔记、课程,甚至在互联网上,但我仍然无法弄清楚最后一个作业问题要求我做什么,即:
编写一个通用的“大于”函数,它接受两个对象作为参数,每个对象都有一个“值”方法,该方法返回一个整数并返回其“值”方法返回较大整数的参数。你的泛型函数应该约束它的类型参数,这样就不能使用没有“值”方法的类型。
引号中的“值”是否有原因以及方法如何约束其类型参数以便不能使用没有“值”方法的类型。我主要是要求澄清或举个小例子。我是否创建了一个 Value 类,然后做这样的事情:
public static <T> int greaterThan(Value obj1, Value obj2){ // Value will have the "value" method?
// do I compare the objects here or in the Value class?
}
解决方案
他们显然是在要求您实现一个通用maxByValue
方法。由于greater-than
包含连字符,因此无论如何都是无效的 Java 标识符,我将坚持使用maxByValue
.
有一个value
方法的要求被提到了几次,所以让我们把它编码为一个接口:
interface Value {
int value();
}
现在,这里有一个泛型参数的主要目的是确保返回类型maxByValue
足够具体以便有用。我们称这种类型T
。为了使参数具有可比性,T
必须是 的子类型Value
。获取返回类型的唯一有意义的来源是参数的类型。综合三点:
- 类型参数
T
子类型Value
- 从参数推断的类型
- 结果类型为
T
给你签名:
public static <T extends Value> T maxByValue(T a, T b)
基本上只有两种有意义的实现方式。让我们采用左偏的(即,如果值相同,则返回左参数):
public static <T extends Value> T maxByValue(T a, T b) {
if (a.value() < b.value()) {
return b;
} else {
return /* left as an exercise */;
}
}
让我们在一个简单的整数示例上尝试一下:
class IntValue implements Value {
final int v;
public IntValue(int v) {
this.v = v;
}
public int value() {
return v;
}
@Override
public String toString() {
return "" + v;
}
}
IntValue a = new IntValue(42);
IntValue b = new IntValue(58);
IntValue c = max(a, b);
System.out.println(c); // prints "58"
到目前为止,一切都很好。让我们看看类型推断有多精确:
static interface Vehicle extends Value {
String doGenericVehicleSound();
}
static abstract class Car implements Vehicle {
public abstract String doCarSpecificSound();
public String doGenericVehicleSound() {
return doCarSpecificSound();
}
}
static class Train implements Vehicle {
public String doGenericVehicleSound() {
return "tk-tk-------tk-tk--tk-tk--------------tk-tk";
}
public int value() {
return 10000000;
}
}
static class Ferrari extends Car {
public String doCarSpecificSound() {
return "rr-rrr-rrrr-rrrrrrr-rrrrrrrrrrrrrrrrrrrr-RRRRRRRRRR";
}
public int value() {
return 222000;
}
}
static class Tesla extends Car {
public String doCarSpecificSound() {
return "... ... ¯\\_(ツ)_/¯";
}
public int value() {
return 50000;
}
}
public static void main(String []args){
System.out.println(maxByValue(new Ferrari(), new Tesla()).doCarSpecificSound());
System.out.println(maxByValue(new Tesla(), new Train()).doGenericVehicleSound());
// System.out.println(maxByValue(new Tesla(), new Train()).doCarSpecificSound());
}
这里要看的要点如下。我们有以下子类型关系:
Train extends Vehicle
Car extends Vehicle
Ferrari extends Car
Tesla extends Car
以及具体实例的以下最小上限:
LUB(Train, Train) = Train
LUB(Train, Ferrari) = Vehicle
LUB(Train, Tesla) = Vehicle
LUB(Ferrari, Ferrari) = Ferrari
LUB(Ferrari, Tesla) = Car
LUB(Tesla, Tesla) = Tesla
(以及所有对称情况)。
现在,当我们
- 把两辆车放进去
maxByValue
,我们拿出一辆车(第一个例子),但是 - 当我们将汽车和火车放入
maxByValue
时,我们会得到更通用的Vehicle
,因此特定于汽车的方法变得不可用(示例二和三;第三个没有编译 - 正确,因为火车没有汽车方法)。
推荐阅读
- python - 如何测试一个字符串是否部分包含在 Python 的列表中
- python - 在 for 循环中创建的 lambda 函数被覆盖
- perl - 动态 PDF 表单 CAM::PDF + PDFLib
- python-3.x - 在 python IDE (pycharm) 中显示谷歌地图或 gmaps
- asp.net-mvc - 如何让 Visual Studio 视图编辑器和预编译器使用 C# 7?
- karate - 空手道:使用来自 API1 响应的一个动态字段为 POST API2 创建 Json 请求正文
- c++ - 由于第二个参数,我的函数并不总是有效
- javascript - 从对象数组中删除重复项的更好算法是什么?
- python - RandomForestClassifier 获得前 N 个预测和相应的概率
- c++ - 从 WCHAR 转换为 const unsigned char