Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/332.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java和Python中继承的区别_Java_Python_Inheritance - Fatal编程技术网

Java和Python中继承的区别

Java和Python中继承的区别,java,python,inheritance,Java,Python,Inheritance,执行的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 0 0 执行的模拟Java代码: public class Test

执行的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
0
0
执行的模拟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;
}
给出:

1
1
0
0
显然,从基类(Test)继承的Java方法也使用基类的成员变量。Python方法使用派生类(子类)的成员变量

问题是:有没有办法在Java中实现与Python相同或至少相似的行为?

使用,而不是重新定义字段:

public class Test {
   int item = 0;

   ...
}

public class Subclass extends Test {
    {
        item = 1;
    }
}

注意:根据您的包结构,您可能希望将
项声明为。

Python中的对象与Python中的字典非常相似。您可以将
测试
子类
的每个实例看作是一个字典,由您声明的类体中的
\uuuuu init\uuuuuu>代码和赋值更新。您可以想象您编写的代码是这样工作的:

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类型,因此
item
只是您碰巧拥有的实例的一些属性。请注意,您实际上不必声明项,只需指定一个值即可。这就是为什么您能够“覆盖”子类中的值,因为您实际上只是覆盖同一字段的旧值。因此,在您给出的示例中,
子类
中的
实际上并没有覆盖
测试中的
;相反,它们是Python对象实例中的同一字段

在Java中,字段实际上属于特定的类。请注意,在代码中,实际上有两个字段
int item
的声明:一个在
Test
中,另一个在
子类中。在
子类
中重新声明
int项
时,实际上是在隐藏原始字段。有关更多信息,请参阅

我不确定您想用示例做什么,但这是一种更惯用的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
的,现在有一个getter和setter方法来访问它。这更像是Java风格的封装

这似乎需要很多代码,但是一个好的IDE(比如Eclipse或IntelliJ)会自动为您生成很多代码。我仍然认为这是一个锅炉板虽然很多,这就是为什么我更喜欢Scala,但这是一个完全不同的讨论

编辑:

我的帖子太长了,以至于我忘了为什么我要引进能手和二传手。要点是,通过封装对字段的访问,您可以执行与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


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

您可以重载超类构造函数,以将
测试中的
字段初始化为0:

public class Test {
    int item = 0;

    Test(){
        System.out.println(this.item);
    }

    Test(int item) {
        this.item = item;
        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 {

    public Subclass() {
        super(1);
    }
}

@flep这是Java中实现与python类似结果的入侵性最小的方法,您可以创建一个构造函数来初始化
,但是根据OP的需要,这个解决方案也可以工作。太好了!二传手和接球手都很痛苦,但效果很好。