adj*_*nks 5 java casting class
在 Java 中,我得到了一项任务。我可以大致如下描述我的问题:
创建三个类 AB 和 C。
类 A 具有实例变量 j,k,l、setter 和 getter 方法,以及基于它们进行计算的方法 x。
类 B 是 A 的子类,并使用 j,k,l 覆盖具有相同空签名的方法 x。
C 类也是 A 的子类,并且有一个额外的类 y 来处理其他垃圾。
现在,实例化一个类 C 对象,设置它的变量,执行方法 x,然后使用类 B 中方法 x 的覆盖版本。
我的问题是,我该如何做最后一部分?我认为这个问题要么不正确,要么我解释错了。我可以将 C 类对象转换为 B 类对象,然后使用 x() 的 B 类版本吗?我不太了解投射对象以及决定是否可以从一件事投射到另一件事的因素。向上投射可能与“水平/横向”投射一样有损,但我从未听说过后者。如果不让 C 类在内部实例化并从它自己的变量重建 B 类对象,是否不可能在类 C 中使用类 B 中的方法?我说的有道理吗?
附录:
好的。所以兄弟姐妹不能被铸造成彼此?因为 C 和 B 都是“[我的] 对象层次结构的一部分”。我可以转换然后返回到不同的子类吗?就像将猫转换为动物类,然后将动物转换为狗?因为方法 x 依赖于类 A 和类 B 中的实例变量,所以在 C 中创建 B 的新实例将创建一个对象,其字段/变量设置不相同,它们都为零或相似。所以我基本上必须将 j、k 和 l 的每个值复制到 C 类对象中的新 B 类型对象中。这似乎是浪费时间和内存,将对象变量复制到另一个非常相似的对象中。但是就没有其他办法了吗?
第二个附录:
虽然我已经选择了一个答案,但我仍然对一般的铸造和我所说的横向铸造很好奇。如果 B 和 C 都是 A 的子类,是否可以允许从 B 转换为 C?另外,一般情况下如何允许铸造?
第三:
所以在这一点上,几年后我明白这在 Java 中是不可能的。然而,有趣的是,在 JavaScript 和 PHP 中,您可以使用函数的“绑定”方法来更改它的上下文,以便它本质上认为它是另一个对象。所以在这个场景中,我可以创建一个B:x() bound的副本到一个C包含我设置的属性的实例,然后 x 的绑定实例将使用 C 实例的所有内部变量。这真的很奇怪,但有时真的很方便。
下面是在另一个子类上使用一个子类的方法的示例;使用狗的说话功能让猫说话:
class Animal {
constructor(){
}
}
class Dog extends Animal{
constructor(){
super()
this.sound = 'bark'
}
speak(){
console.log(this.sound)
}
}
class Cat extends Animal{
constructor(){
super()
this.sound = 'meow'
}
}
var mycat = new Cat()
var mydog = new Dog()
mydog.speak()
mydog.speak.bind(mycat)()Run Code Online (Sandbox Code Playgroud)
所以基本上就好像 cat 有说话功能一样。这是我想在 Java 中做的事情。
强制转换意味着您比编译器更了解您的对象是什么。如果您转换为不属于对象层次结构的内容,那么在运行程序时您将收到异常(特别是ClassCastException )。
最常见的地方是在 Object#equals 方法中。equals 需要将 java.lang.Object 作为其唯一参数。如果您查看人们如何实现 equals,您将看到测试传入对象的类是什么,如果它是预期的,则进行强制转换,以便随后的检查可以使用该对象的字段。否则,在初学者情况下铸造不会出现太多。
强制转换不会改变对象是什么,它只是试图告诉编译器在类型系统不充分的情况下(例如 equals)该对象是什么。如果您在层次结构中使用虚拟方法创建对象,则转换不会更改调用的方法版本。
如果 C 不是 B 的子类,那么您可以在 C 中创建 B 类的对象,作为 B 的某个方法的实例成员或局部变量,并调用 C 的方法,如下所示:
class C extends A {
private B b; // instance member
public C(B b) {
this.b = b;
}
public void x() {
// do stuff
b.x();
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1426 次 |
| 最近记录: |