Python3与Java的简单对比之面向对象

类(class)是构造对象的模板或蓝图。由类构造(construct)对象的过程称为创建类的实例(instance)。

Java核心技术

类提供了一种组合数据和功能的方法。创建一个新类意味着创建一个新类型的对象,从而允许创建一个该类型的新实例。

Python3.7.4文档

在对于类的定义上,Python3与Java定义一致。

​ 下面分别用Java和Python3编写一个People类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
/**
* People
*/
public class People {
//实例域(成员变量)
private String name;
private int age;
private String gender;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

public String getGender() {
return gender;
}

public void setGender(String gender) {
this.gender = gender;
}

//无参构造器
public People() {
System.out.println("【JPeople】无参构造器");
}

//带参构造器
public People(String name, int age, String gender) {
System.out.println("【JPeople】带参构造器");
this.name = name;
this.age = age;
this.gender = gender;
}

//静态方法
public static void f() {
System.out.println("【JPeople】静态方法");
}

//实例方法
public void sayHello() {
System.out.println("【JPeople】"+this.name + " say:\"Hello\"");
pf();
}

//私有方法
private void pf(){
System.out.println("【JPeople】私有方法");
}
}

public class PeopleTest {
public static void main(String[] args) {
People tom = new People("tom", 18, "male");
tom.sayHello();
People.f();
}
}

​ Java执行结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
class People:
"""People"""
# 私有属性
__gift = 100
# 类属性
name = ''
age = 0

# 限定对象只能绑定_gender属性
# __slots__=('_gender')

# 实例化方法
def __init__(self, name, age, gender):
print("【PPeople】构造方法")
self.name = name
self.age = age
self._gender = gender

# getter方法
@property
def gender(self):
return self._gender

# setter方法
@gender.setter
def gender(self,gender):
self._gender=gender

# 静态方法
@staticmethod
def sf():
print("【PPeople】静态方法")

# 类方法
@classmethod
def cf(cls):
print("【PPeople】类方法")

# 实例方法
def say_hello(self):
print("【PPeople】{} say:\"Hello!\",gift={}".format(self.name, self.__gift))
self.__pf()

# 私有方法
def __pf(self):
print("【PPeople】私有方法")

People.age += 1
print(People.age)
People.sf()
tom = People('Tom', 18, 'male')
tom.gender="female"
print(tom.gender)
tom.say_hello()

​ Python执行结果

小结

Java Python
私有属性 (成员变量)使用private关键字修饰 属性名双下划线开头__;不建议将属性设置为私有,建议以_(单下划线)开头,暗示属性为受保护的,不建议外部直接访问,建议使用getter、setter进行操作
类属性 使用static修饰的变量 类和对象都可以访问
构造方法 有参、无参构造器;方法名与类名相同 (实例化方法)方法名固定__init__
实例方法 对象访问 (普通方法)对象访问,默认有参self
私有方法 使用private关键字修饰 方法名双下划线开头__
静态方法 使用static关键字修饰 使用@staticmethod装饰器,可以无参
类方法 同静态方法 使用@classmethod装饰器,类和对象访问,默认参数cls

继承

​ 在Java中类只能单继承继承,因为Java的设计者认为,多继承会让语言本身变得非常复杂(如同C++),效率也会降低(如同Eiffrl),而为了让程序设计更加灵活,Java中就有了接口(interface),接口之间可以多继承。而Python的类可以多继承,也就没必要有接口;下面分别使用Java和Python 3实现Student子类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class Student extends People{

//学号
private String studentNumber;

public String getStudentNumber() {
return studentNumber;
}

public void setStudentNumber(String studentNumber) {
this.studentNumber = studentNumber;
}
//子类无参构造器
public Student() {

}
//带参构造器
public Student(String name, int age, String gender, String studentNumber) {
//调用父类带参构造器
super(name, age, gender);
System.out.println("【JStudent】带参构造器");
this.studentNumber = studentNumber;
}

//重写父类方法
public void sayHello(){
System.out.println("【JStudent】"+this.getName() + " say:\"Hello\"");
}

public static void main(String[] args) {
Student student_1 = new Student("Jerry", 17, "male", "0021");
student_1.sayHello();
}
}

​ Java执行结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# 单继承
class Student(People):
# 子类构造方法
def __init__(self, name, age, gender, student_number):
print("【PStudent】构造方法--开始")
# 调用超类构造方法
super(Student, self).__init__(name, age, gender)
self.student_number = student_number
print("【PStudent】构造方法--结束")

# 重写父类方法
def say_hello(self):
print("【PStudent】{} say:\"Hello!\"".format(self.name))

# Child类,为多继承做准备
class Child:
def __init__(self, name, mom, dad):
print("【PChild】构造方法")
self.name = name
self.mom = mom
self.dad = dad

def cry(self):
print('【PChild】'+self.name + ":\'wow wow\'")

# 多重继承
class Kid(Student, Child):
def __init__(self, name, age, gender, student_number, mom, dad):
print("【PKid】构造方法--开始")
Student.__init__(self, name, age, gender, student_number)
Child.__init__(self, name, mom, dad)
print("【PKid】构造方法--结束")

def info(self):
print('【PKid】'+', '.join(['%s:%s' % item for item in self.__dict__.items()]))

# 创建一个Student对象
jerry = Student("Jerry", 17, 'male', '0021')
print(jerry.name)
jerry.say_hello()
# 创建一个Kid对象
kid = Kid("小明", 12, "男", "0023", "Tom", "Jerry")
kid.info()

​ Python执行结果

小结

​ Java与Python 3 在掉用构造方法时顺序是一致的,但是Java在构造方法内调用父类构造方法,语句super()必须放在方法体的第一句;而Python 3,对象是由 __new__()__init__()协作构造完成,实例通过__new__方法被创建,使用__init__方法进行初始化;所以在调用父类方法之前,可以对参数进行定制修改。Python 3 的多继承,在搜索从父类继承的方法/属性时,可以简单认为是深度优先、从左至右;但为了保持单次调用,实际在调用时是动态的;

多态

​ 实现多态的步骤:1.继承父类 2.重写父类方法 3.向上转型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**1.Teacher继承自People**/
public class Teacher extends People {

public Teacher() {
}

public Teacher(String name, int age, String gender) {
super(name, age, gender);
}
//2.重写sayHello方法
public void sayHello() {
System.out.println("【JTeacher】"+this.getName() + ":\" 同学们早上好!\"");
}
}
1
2
3
4
5
6
7
8
9
public class Test {
public static void main(String[] args) {
//3.向上转型
People teacher= new Teacher("王阳明",45,"男");
teacher.sayHello();
People student =new Student("小明", 17, "男", "0021");
student.sayHello();
}
}

java运行结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Teacher(People):
"""继承自People"""
def __init__(self, name, age, gender):
print("【PTeacher】构造方法--开始")
super(Teacher, self).__init__(name, age, gender)
print("【PTeacher】构造方法--结束")

def say_hello(self):
print("【PTeacher】{} say:\"同学们好!\"".format(self.name))

people_1 = Student("小明", 12, "男", "0023")
people_1.say_hello()
people_2 = Teacher("王阳明", 45, "男")
people_2.say_hello()

Python运行结果:

小结

Python从语法层面并没有像Java那样提供对抽象类的支持,但是我们可以通过abc模块的ABCMeta元类和abstractmethodclass CLASSNAME(metaclass=ABCMeta):)包装器来达到抽象类的效果,如果一个类中存在抽象方法那么这个类就不能够实例化。