根据Joshua Blotch的有效Java:
除非您愿意放弃面向对象抽象的好处,否则在保留compareTo契约的同时,无法使用新的值组件扩展可实例化类
你能用例子和挑战来解释以上内容吗?你能解释一下Joshua所说的“价值成分”是什么意思,以及还有哪些其他类型的成分可用吗。
这使您可以在第二类上实现您喜欢的任何comareTo
方法,同时允许其客户端在需要时将第二类的实例视为第一类的实例。
你能解释一下约书亚所说的“第二类”是指“第一类”吗?
compareTo
方法
你能用例子和挑战来解释以上内容吗?
当然。考虑像这样的两个类——我忽略了所有的getter、setter等,但希望你能明白:
class NamedThing {
String name;
}
class Person extends NamedThing {
Date dateOfBirth;
}
忽略这是否是一个继承的好例子——这是一个简单的例子。
对于NamedThing
来说,按字母顺序实现基于名称的比较是很自然的。
Person
执行一个比较也是很自然的,它首先比较姓名(因此在这方面保持一致),然后检查一个出生日期是否早于另一个。
现在想象一下:
NamedThing person1 = new Person("Jon", date1);
NamedThing person2 = new Person("Jon", date2);
NamedThing thing = new NamedThing("Jon");
int comparison1 = person1.compareTo(thing);
int comparison2 = person2.compareTo(thing);
int comparison3 = person1.compareTo(person2);
int comparison4 = thing.compareTo(person1);
您希望所有这些结果是什么?如果Person.compareTo
足够聪明,只将其日期处理应用于Person
的实例,那么您可能期望比较1
和比较2
为0,但比较3
为非零。
大概comparison4
必须为0,因为它使用NamedThing。compareTo
,它只比较名称。
从根本上说,试图比较不同类型的实例是一个问题。比较的外部定义最终会更简洁,定义了它将使用的比较。因此,您可以有一个比较器
你能解释一下约书亚所说的“第二类”是指“第一类”吗?
你断章取义了。它是:“将第二个类的实例视为第一个类的实例”——例如。
// First class = Animal
// Second class = Zebra
Animal person = new Zebra();
Joshua Blotch的《有效Java》中写道: 除非您愿意放弃面向对象抽象的好处,否则在保留
我正在创建一个Minecraft 1.12.2 mod(forge 1.12.2-14.23.1.2555),并创建了一个扩展ItemAxe的新类。当我将新类实例化为变量时,该变量返回null。因此,在注册该项时,会引发NullPointerException。在我尝试将ItemAxe的扩展名改为ItemAxe之后,我开始考虑这个问题。运行了代码,它成功了。将其更改回ItemAxe,运行代码,但不
问题内容: 我明白: 由于抽象类本身并不是什么,例如车辆,我们想要创建一个具体实现的对象,例如Car,Bike等。 对象链期间将调用抽象类的构造函数。 我们永远不能直接创建抽象类的对象,即使它包含构造函数并且所有方法都已实现。 但是从编译器的角度来看,Java为什么要强制执行这些规则? 问题答案: 这不是技术限制,而是(如您所指出的)逻辑上的限制。Java(和许多其他语言)执行各种规则不是因为它们
类别:账户余额 我已经把这两个类都放在Balance.java和Account tBalance.java.这两个文件都在E:/程序/MyPack. Balance.java编译没有错误但是当我编译Account tBalance.java它给出错误:找不到符号"平衡". 我无法弄清楚为什么当两个类都在同一个包中声明时? 我正在使用javac B从MyPack编译alance.javajavac
我有以下功能: <代码>坐标 这是它的重载==运算符: 如果(c==i),它会在以下位置给我一个错误: 错误:传递“常量坐标”
我已经完成了一些Java教程,它们都说在调用类时创建一个新变量。这是为什么?我已经测试了一些代码,但它没有这样做。我已经使用python很长一段时间了,所以我习惯于使用动态语言。 请看下面我一直在玩的一些代码: 谢谢你的时间。