比较Python与Java在类的定义、继承、多态等方面的异同

发布时间 2023-04-25 10:27:51作者: YE-

首先我来进行介绍Python与Java在类的定义、继承、多态等方面的异同

1.python类和java类的使用一览


java:

public class Car {

    private String color;

    private String model;

    private int year;

 

    public Car(String color, String model, int year) {

        this.color = color;

        this.model = model;

        this.year = year;

    }

 

    public String getColor() {

        return color;

    }

 

    public String getModel() {

        return model;

    }

 

    public int getYear() {

        return year;

    }

}

 

python:

class Car:

    def __init__(self, color, model, year):

        self.color = color

        self.model = model

        self.year = year

从代码行上来看,显然还是python的代码行较少,显得较为简洁,同时,这个也可以被称为Python的优点之一。而且从中也可以明显看出python类中的变量可以直接使用,但是java中使用变量需要先声明再使用。

2.Python的继承

python和java在继承方面最大的区别就是python子类可以继承多个父类,但是java子类只能继承一个父类,如果一个子类需要多继承的话一般设计成interface接口的方式来实现。比如创造一个child类,类型fathermother。在Python中,father类和mother类可以都设计成child的父类,但在java中可以设计成father父类和mother接口,继承需要extends关键字实现,接口需要implements关键字实现


python实现

class child(father,mother):

java实现

class child extends father implements mother

3. Python多态

java中的多态跟Python中的多态是有区别的。java中的多态定义:

多态存在的三个必要条件

1、要有继承;

2、要有重写;

3、父类引用指向子类对象。

java多态演示


public class Test {

    public static void main(String[] args) {

      show(new Cat());  // 以 Cat 对象调用 show 方法

      show(new Dog());  // 以 Dog 对象调用 show 方法

                

      Animal a = new Cat();  // 向上转型  

      a.eat();               // 调用的是 Cat 的 eat

      Cat c = (Cat)a;        // 向下转型  

      c.work();        // 调用的是 Cat 的 work

  }  

            

    public static void show(Animal a)  {

      a.eat();  

        // 类型判断

        if (a instanceof Cat)  {  // 猫做的事情 

            Cat c = (Cat)a;  

            c.work();  

        } else if (a instanceof Dog) { // 狗做的事情 

            Dog c = (Dog)a;  

            c.work();  

        }  

    }  

}

 

abstract class Animal {  

    abstract void eat();  

}  

  

class Cat extends Animal {  

    public void eat() {  

        System.out.println("吃鱼");  

    }  

    public void work() {  

        System.out.println("抓老鼠");  

    }  

}  

  

class Dog extends Animal {  

    public void eat() {  

        System.out.println("吃骨头");  

    }  

    public void work() {  

        System.out.println("看家");  

    }  

}

#执行以上程序,输出结果为:

#吃鱼

#抓老鼠

#吃骨头

#看家

#吃鱼

#抓老鼠

Python多态

类具有继承关系,并且子类类型可以向上转型看做父类类型,如果我们从 Person 派生出 Student和Teacher ,并都写了一个 whoAmI() 方法:

class Person(object):

    def __init__(self, name, gender):

        self.name = name

        self.gender = gender

    def whoAmI(self):

        return 'I am a Person, my name is %s' % self.name

 

class Student(Person):

    def __init__(self, name, gender, score):

        super(Student, self).__init__(name, gender)

        self.score = score

    def whoAmI(self):

        return 'I am a Student, my name is %s' % self.name

 

class Teacher(Person):

    def __init__(self, name, gender, course):

        super(Teacher, self).__init__(name, gender)

        self.course = course

    def whoAmI(self):

        return 'I am a Teacher, my name is %s' % self.name

在一个函数中,如果我们接收一个变量 x,则无论该 x 是 Person、Student还是 Teacher,都可以正确打印出结果:

 

def who_am_i(x):

    print x.whoAmI()

 

p = Person('Tim', 'Male')

s = Student('Bob', 'Male', 88)

t = Teacher('Alice', 'Female', 'English')

 

who_am_i(p)

who_am_i(s)

who_am_i(t)

运行结果:

I am a Person, my name is Tim

I am a Student, my name is Bob

I am a Teacher, my name is Alice

这种行为称为多态。也就是说,方法调用将作用在 x 的实际类型上。s 是Student类型,它实际上拥有自己的 whoAmI()方法以及从 Person继承的 whoAmI方法,但调用 s.whoAmI()总是先查找它自身的定义,如果没有定义,则顺着继承链向上查找,直到在某个父类中找到为止。

由于Python是动态语言,所以,传递给函数 who_am_i(x)的参数 x 不一定是 Person 或 Person 的子类型。任何数据类型的实例都可以,只要它有一个whoAmI()的方法即可:

class Book(object):

    def whoAmI(self):

        return 'I am a book'

这是动态语言和静态语言(例如Java)最大的差别之一。动态语言调用实例方法,不检查类型,只要方法存在,参数正确,就可以调用。


# 其次我来介绍总结Python面向对象程序设计中的原则和注意事项

## 一、继承

与java的继承不同python支持多继承,如Person类同时继承Animal类和Species类可以这样写:

class Animal(object):

    def __init__(self):

        pass



class Species:

    def __init__(self):

        pass



class Person(Animal, Species):

    country = "CN"



    def __init__(self, name, age, sex):

         # super(Animal,self) 首先找到父类,然后把类Person的对象转换为类Animal的对象

        super(Animal,self).__init__()

        self.name = name

        self.age = age

        self.sex = sex



    def printString(self):

        print("name:" + self.name + "\n" + "age:" + str(self.age) + "\n" + "sex:" + self.sex)



person = Person("Jack", 12, "male")

print(person.printString())

**括号里的即为父类,多类继承支持优先级如下:**

![image.png]({PTA_URL}/api/private-image?p=user-uploads/1438664011951128576/2023-4-25/1682353930-0a28eb9a-4a08-400d-bbd6-898fd2f17e01.png)

>该图片是网图

## 二、是否继承object类的区别

![image.png]({PTA_URL}/api/private-image?p=user-uploads/1438664011951128576/2023-4-25/1682353982-8b7110a7-3053-482d-8105-5fe9e338c2b5.png)

继承了object以后类会增加一些属性,不影响基本使用。

## 三、封装

与java不同python没有private关键字,使用方法是在方法或变量前加“__”

如:

class Person(Animal, Species):

    __country = "CN"



    def __init__(self, name, age, sex):

        self.name = name

        self.age = age

        self.__sex = sex



    def __breath(self):

        print(self.name+"在呼吸.......")



    def printString(self):

        self.__breath()

        print("name:" + self.name + "\n" + "age:" + str(self.age) + "\n" + "sex:" + self.__sex)



person = Person("Jack", 12, "male")

print(person.printString())

print(person._Person__sex)

print(person._Person__country)

person._Person__breath()

设置了“__”后就表示为私密变量或方法。

但python里却有破解私密访问的方法:

即:对象._类名__方法名()或变量名

保密性如下:

>__foo__: 定义的是特殊方法,一般是系统定义名字 ,类似 __init__() 之类的。

>_foo: 以单下划线开头的表示的是 protected 类型的变量,即保护类型只能>允许其本身与子类进行访问,不能用于 from module import *

>__foo: 双下划线的表示的是私有类型(private)的变量, 只能是允许这个类本身进行访问了。

>foo:就是public方法

## 四、类方法、静态方法与属性方法

类方法,不能调用实例变量或方法,只能调用类方法或变量,使用时需要在方法上添加“@classmethod”,如下:

```    class Person(object):

        _number = 0

 

        def __init__(self, name, age, sex):

            self.name = name

            self.age = age

            self._number = 2  # 这里操作的是实例对象的变量

            Person._number += 1  # 这里对类的静态变量进行操作

            self.__sex = sex

 

        def __breath(self):

            print(self.name + "在呼吸.......")

 

        @classmethod

        def lucky(cls):  # cls代表class类本身与self或this不同,self和this代表实例对象

            person2 = Person("Alex", 13, 'male')

            person2.printString()

            print(cls._number)  # 输出类变量

 

        def printString(self):

            self.__breath()

            print("name:" + self.name + "\n" + "age:" + str(self.age) + "\n" + "sex:" + self.__sex)

 

    person = Person("Jack", 12, "male")

    person.printString()  # 调用时用实例对象

    Person.lucky()  # 调用时用类

也可以使用静态方法的注解“@staticmethod”类

静态方法,不能调用类或实例的任何变量

属性方法使用注解“@property”,特点是调用时和调用属性变量类似。


    class Person(object):

 

        def __init__(self, name, age, sex):

            self.name = name

            self.age = age

            self.__sex = sex

 

        @property

        def lucky(self):  # cls代表class类本身与self或this不同,self和this代表实例对象

            print("233")

 

        @lucky.setter

        def lucky(self, num):  # cls代表class类本身与self或this不同,self和this代表实例对象

            print("233")

            self.num = num

 

    person = Person("Jack", 12, "male")

    person.lucky  # 调用时像调用属性变量一样调用

    person.lucky = 1  # 传参和变量传参类似

    print(person.num)

属性方法可以调用类和属性变量,传参和变量传参类似。

五、多态


    class Animal(object):  #相对于抽象类

        def show(self):

            print("abstract class must be rewrite!")

            raise Exception

 

    class Person(Animal):

 

        def __init__(self, name, age, sex):

            self.name = name

            self.age = age

            self.__sex = sex

 

        def show(self):

            print("hello")

 

    person = Person("Jack", 12, "male")

    print(person.show())

六、python是否存在实质意义上的私有变量?

回答:

不存在的

Python中没有禁止访问类中某一成员的保护机制。Java是一门非常工程化的语言,其哲学就是为工程服务,通过各种限制,尽可能减少程序员编写错误代码的机会。而Python则相反,其哲学为信任编码者,给程序员最少的限制,但程序员必须为自己编写的代码负责。

那是否意味着Python认为面向对象编程不需要封装呢?答案也是否定的。Python通过编码规范而不是语言机制来完成封装,具体而言,Python规定了对变量命名的公约,约定什么样的变量名表示变量是私有的,不应该被访问(而不是不能被访问)。