执行的Python代码:
class Test(object):
item = 0
def __init__(self):
print(self.item)
def test(self):
print(self.item)
class Subclass(Test):
item = 1
s = Subclass()
s.test()
给出:
^{pr2}$执行的模拟Java代码:
public class Test {
int item = 0;
Test(){
System.out.println(this.item);
}
void test(){
System.out.println(this.item);
}
public static void main(String[] args){
Subclass s = new Subclass();
s.test();
}
}
class Subclass extends Test {
int item = 1;
}
给出:
0
0
显然,从基类(Test)继承的Java方法也使用基类的成员变量。Python方法使用派生类(子类)的成员变量。在
问题是:有没有办法在Java中实现与Python相同或至少相似的行为?在
您可以重载超类构造函数,将
Test
中的字段item
初始化为0:Python中的对象非常类似于Python中的字典。您可以将}的每个实例看作一个字典,它由您声明的类的主体中的
Test
和{__init__
代码和赋值更新。你可以想象你写的代码是这样工作的:Python使用duck类型,因此
item
只是您碰巧拥有一个实例的某个属性。请注意,您实际上不必声明项,只需分配一个值。这就是为什么您能够“重写”子类中的值,因为实际上您只是覆盖同一字段的旧值。所以在您给出的示例中,Subclass
中的item
实际上并不是覆盖Test
中的item
;相反,它们是Python对象实例中的相同字段。在在Java中,字段实际上属于特定的类。注意,在代码中,实际上有两个字段
int item
的声明:一个在Test
中,一个在Subclass
中。当您在Subclass
中重新声明int item
时,实际上是在对原始字段进行跟踪。有关详细信息,请参见Java in a Nutshell: 3.4.5. Shadowing Superclass Fields。在我不确定您到底想用您的示例做什么,但这是一种更惯用的Java方法:
^{pr2}$请注意
item
的值是如何通过构造函数参数而不是通过简单赋值来设置的。还要注意item
是private
,现在有一个getter和setter方法来访问它。这是更多的Java风格的封装。在这看起来有很多代码,但是一个好的IDE(比如Eclipse或IntelliJ)会自动为您生成大量代码。我仍然认为这是一个很大的锅炉板,这就是为什么我喜欢Scala,但这是一个完全不同的讨论。在
编辑:
我的帖子太长了,以至于我不知道为什么要介绍getter和setters。关键在于,通过封装对字段的访问,您可以执行类似于Python中的操作:
现在,
item
字段已经被有效地覆盖了,因为对它的所有访问都是通过getter和setter完成的,并且这些字段已经被重写以指向新字段。但是,这仍然会导致输出中出现0 1
,而不是预期的1 1
。在这种奇怪的行为源于这样一个事实:您从构造函数中打印,这意味着对象实际上还没有完全初始化。如果在构造期间将
this
引用传递到构造函数之外,这尤其危险,因为它可能导致外部代码访问不完整的对象。在使用initializer而不是重新定义字段:
注意:根据您的包结构,您可能希望将} 。在
item
声明为^{相关问题 更多 >
编程相关推荐