gpt4 book ai didi

java - Java 和 Python 中继承的区别

转载 作者:太空狗 更新时间:2023-10-29 21:32:16 25 4
gpt4 key购买 nike

执行的 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()

给出:

1
1

执行类比 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方法使用派生类(Subclass)的成员变量。

问题:有什么方法可以在 Java 中实现与在 Python 中相同或至少相似的行为?

最佳答案

Python 中的对象与 Python 中的字典非常相似。您可以将 TestSubclass 的每个实例都看作是一个字典,由类主体中的 __init__ 代码和赋值更新宣布。您可以想象您编写的代码是这样工作的:

class Test(object):         
item = 0 # self['item'] = 0

def __init__(self):
print(self.item) # print(self['item'])

def test(self):
print(self.item) # print(self['item'])

class Subclass(Test):
item = 1 # self['item'] = 1

s = Subclass() # Test.__init__({})
s.test()

Python 使用 duck-typing,因此 item 只是您碰巧拥有的任何实例的一些属性。请注意,您实际上不必声明 项目——您只需分配一个值。这就是您能够“覆盖”子类中的值的原因——因为您实际上只是覆盖了同一字段的旧值。所以在你给出的例子中, Subclass 中的 item 实际上并不是 overriding 中的 item测试;相反,它们是 Python 对象实例中的相同字段。

在 Java 中,字段实际上属于特定的类。请注意,在您的代码中,您实际上有 两个声明 字段 int item:一个在 Test 中,一个在 Subclass 中>。当您在 Subclass 中重新声明 int item 时,您实际上是在隐藏 原始字段。参见 Java in a Nutshell: 3.4.5. Shadowing Superclass Fields了解更多信息。

我不确定你到底想用你的例子做什么,但这是一种更惯用的 Java 方法:

public class Test {

private int item;

public Test() {
this(0); // Default to 0
}

public Test(int item) {
setItem(item);
test();
}

public void test() {
System.out.println(getItem());
}

public static void main(String[] args) {
Subclass s = new Subclass();
s.test();
}

public void setItem(int item) {
this.item = item;
}

public int getItem() {
return item;
}

}

class Subclass extends Test {

public Subclass() {
super(1); // Default to 1
}

}

注意 item 的值是如何通过构造函数参数而不是简单赋值来设置的。还要注意 item 是如何成为 private 的,并且现在有一个 gettersetter 方法来访问它。这是更Java风格的封装。

这似乎有很多代码,但一个好的 IDE(例如 Eclipse 或 IntelliJ)会自动为您生成很多代码。我仍然认为它有很多样板,这就是我更喜欢 Scala 的原因——但这是一个完全不同的讨论。

编辑:

我的帖子太长了,以至于我忘记了为什么要介绍 getter 和 setter。关键是通过封装对字段的访问,您可以做一些更像您在 Python 中所做的事情:

public class Test {
// Same as above . . .
}

class Subclass extends Test {

private int subclassItem = 1;

public int getItem() {
return subclassItem;
}

public void setItem(int item) {
this.subclassItem = item;
}

}

现在,item 字段已被有效覆盖,因为对它的所有访问都是通过 getter 和 setter 完成的,并且这些已被覆盖以指向新字段。但是,这仍然会导致输出中的 0 1 而不是您期望的 1 1

这种奇怪的行为源于您从构造函数中打印的事实——这意味着该对象实际上尚未完全初始化。如果在构造期间将 this 引用传递到构造函数之外,这尤其危险,因为它可能导致外部代码访问不完整的对象。

关于java - Java 和 Python 中继承的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12018863/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com