什么时候需要铸造 'this'?
When would casting 'this' be required?
在 Java 中是否有任何情况需要您明确地将 this
转换为当前 class 以外的其他类型?
class SomeClass
{
void foo()
{
SomeOtherClass s = (SomeOtherClass) this;
}
}
编辑:所有答案均指 SomeOtherClass
是 [= 的子 class 的情况14=],但在这些情况下,通过适当的 OO 设计可以避免强制转换 this
。我正在寻找 OO 无法帮助您的情况,即 SomeOtherClass
是 SomeClass
.[=18 的 super-class =]
当 SomeClass 是 SomeOtherClass 的超class。但是……如果你这样做,这意味着你的 OO 设计有些地方不太正确,你很可能在滥用你的模型。
不,不应该存在需要将 this
强制转换为子类的情况,至少在体面的 OO 设计中不需要。下面的例子只是为了展示如何使用它。
class BaseClass {
public void foo() {
if(this instanceof SomeClass) {
SomeClass s = (SomeClass) this;
s.bar();
} else {
baz();
}
}
private void baz() {
...
}
}
class SomeClass extends BaseClass {
public void bar() {
}
}
只有变窄型和变宽型两种。缩小转换将转换为当前类型未声明实现的子类型或 interface
类型。正如您自己所说,您应该始终能够通过适当的 OO 设计避免这种类型转换的必要性。
考虑到引用类型继承其超类的所有成员,static
成员除外,不能通过 this
和 private
成员,即使使用强制转换也无法访问。 this
的扩大转换可能有用的唯一场景是访问已被另一个同名字段隐藏的字段:
class A {
int foo;
}
class B extends A {
int foo;
}
class C extends B {
{
((A)this).foo=42;
}
}
请注意,在 B
中,一个简单的 super.foo=42;
就足够了,只有 C
需要类型转换才能访问 A.foo
。而且,当然,您可以通过引入该类型的变量来避免每次扩大转换,因为分配给它会使扩大转换隐含:
A tmp=this;
tmp.foo=42;
另一种情况可能是你想调用一个重载方法传递 this
作为参数,但想要 select 接受更广泛类型的重载或者必须 select一个是因为否则它是模棱两可的。不过,这可以通过不进行类型转换的附加变量来解决。
因此,将类型转换应用于 this
应该 总是 是可以避免的。
尽管如此,我不确定每个开发人员是否都在他编写的每个代码中都力求“正确的 OO 设计”。此外,有时开发人员可能更喜欢扩大类型转换而不是临时变量。
在 Java 中是否有任何情况需要您明确地将 this
转换为当前 class 以外的其他类型?
class SomeClass
{
void foo()
{
SomeOtherClass s = (SomeOtherClass) this;
}
}
编辑:所有答案均指 SomeOtherClass
是 [= 的子 class 的情况14=],但在这些情况下,通过适当的 OO 设计可以避免强制转换 this
。我正在寻找 OO 无法帮助您的情况,即 SomeOtherClass
是 SomeClass
.[=18 的 super-class =]
当 SomeClass 是 SomeOtherClass 的超class。但是……如果你这样做,这意味着你的 OO 设计有些地方不太正确,你很可能在滥用你的模型。
不,不应该存在需要将 this
强制转换为子类的情况,至少在体面的 OO 设计中不需要。下面的例子只是为了展示如何使用它。
class BaseClass {
public void foo() {
if(this instanceof SomeClass) {
SomeClass s = (SomeClass) this;
s.bar();
} else {
baz();
}
}
private void baz() {
...
}
}
class SomeClass extends BaseClass {
public void bar() {
}
}
只有变窄型和变宽型两种。缩小转换将转换为当前类型未声明实现的子类型或 interface
类型。正如您自己所说,您应该始终能够通过适当的 OO 设计避免这种类型转换的必要性。
考虑到引用类型继承其超类的所有成员,static
成员除外,不能通过 this
和 private
成员,即使使用强制转换也无法访问。 this
的扩大转换可能有用的唯一场景是访问已被另一个同名字段隐藏的字段:
class A {
int foo;
}
class B extends A {
int foo;
}
class C extends B {
{
((A)this).foo=42;
}
}
请注意,在 B
中,一个简单的 super.foo=42;
就足够了,只有 C
需要类型转换才能访问 A.foo
。而且,当然,您可以通过引入该类型的变量来避免每次扩大转换,因为分配给它会使扩大转换隐含:
A tmp=this;
tmp.foo=42;
另一种情况可能是你想调用一个重载方法传递 this
作为参数,但想要 select 接受更广泛类型的重载或者必须 select一个是因为否则它是模棱两可的。不过,这可以通过不进行类型转换的附加变量来解决。
因此,将类型转换应用于 this
应该 总是 是可以避免的。
尽管如此,我不确定每个开发人员是否都在他编写的每个代码中都力求“正确的 OO 设计”。此外,有时开发人员可能更喜欢扩大类型转换而不是临时变量。