转载

新年总要立flag

一直没有写技术博客的习惯,今年打算开始立flag,在博客这块每周写2篇。主要会把最近在学习的东西做一个总结、记录和反思,作为一个知识输出的途径,也提高一下写作的水平。

那么flag来了,一年52周,一周两篇,明年的元旦我应该可以看到自己写了100篇的博客???希望不要划水,把这件事做好。(这篇也算hhhhhhhhhh)

目前研究生刚刚毕业了,年后会去魔都入职做中台开发,分享的内容可能是工作上遇到的问题的复盘反思,专栏学习的经验总结,经典书籍当中比较有趣的问题等。

今天的主题是Java中的继承与Python的继承之间的区别

public class Test {
    public static void main(String[] args) {
        new A();
        new B();
    }
}

class A {
    int i = 7;

    public A() {
        setI(20);
        System.out.println("i from A is " + i);
    }

    public void setI(int i) {
        this.i = 2 * i;
    }
}

class B extends A {
    public B() {
        System.out.println("i from B is " + i);
    }

    public void setI(int i) {
        this.i = 3 * i;
    }
}

A是B的父类,经过两次对象实例化后,它们i的值分别为多少?

首先在main方法里new了两个实例对象,一个A一个B。

new A();的结果很简单,在其构造函数A()里,将20作为参数传递给了setI,使其成员变量i从7变成了40,然后打印输出。

而new B();语句,由于B是A的父类,构造函数的调用顺序是 先调用父类的构造函数 ,这里setI方法在父类和子类中都有相应的定义,并且有相同的方法签名,属于 方法重写 。因此父类的构造函数里调用的是子类重写后的setI方法,将传递进来的参数扩大了3倍赋值给成员变量i。而这个成员变量i是在父类定义,子类继承过来的,属于同一个实例对象,因此后面两次打印输出i的内容保持一致。

输出结果是

i from A is 40
i from A is 60
i from B is 60

再来看一下python 中的继承

class Person():
    def __init__(self, identity):
        print('Person class init called')
        self.identity = identity
        
    def print_grade(self):
        print(self.grade)

class Student(Person):
    def __init__(self, name, grade):
        print('Student class init called')
        Person.__init__(self, 'student')
        self.name = name
        self.grade = grade
        
s = Student('Adam','newbie')
s.print_grade()

这里Person是Student的父类,类的构造方法由__init__来进行,这边跟java比较不一样的是

  1. 父类的构造函数需要主动调用,因此也可以不调用;
  2. 而且是先进行子类的构造函数,再进行父类的构造函数。
Person.__init__(self, 'student')

当我们把这行代码注释掉时,父类构造函数的打印输出消失了,但是其print_grade()方法还是可以正常使用。

因此这里的猜测是: Python中构造方法并不是构造对象的作用,而只是一个初始化的准备工作的作用。

那么Java呢?也是一样,在jvm创建对象之后,调用构造方法进行初始化的准备工作。

原文  https://segmentfault.com/a/1190000021458263
正文到此结束
Loading...