当前位置:首页>python>从java到Python的面向对象

从java到Python的面向对象

  • 2026-09-02 20:33:06
从java到Python的面向对象

对于很多Java开发者习惯了 Java 的面向对象编程范式,在刚接触 Python 时是不是总觉得很别扭?比如没有public/private关键字、构造方法不能重载、甚至连this都变成了显式的self?今天我们就以一个简单的Squre类为例,一步步了解Python OOP和Java的核心差异。

首先,我们定义一个Java版本的Square类,它继承自抽象的Shape类,包含位置、边长属性和周长面积计算方法:

abstract class Shape {    abstractintarea();    abstractintperimeter();}public class Square extends Shape {    private int x;    private int y;    private int side;    // 构造方法1:直接传入坐标和边长    publicSquare(int x, int y, int side) {        this.x = x;        this.y = y;        this.side = side;    }    // 构造方法2:通过两个对角点计算边长    publicSquare(int x1, int y1,int x2,int y2) {        if(Math.abs(x2 - x1) != Math.abs(y2 - y1) ) {            throw new IllegalArgumentException("Square must have equal sides");        }        x = x1;        y = y1;        side = (x2 - x1);    }    publicintarea() {        return side * side;    }    publicintperimeter() {        return 4 * side;    }    public String toString() {        return String.format("Square[x=%d,y=%d,side=%d", x, y, side);    }}

接下来我们把它转成Python版,看看两者的差异,Java里可以重载多个构造方法,但Python没有方法重载,只能有一个__init__(),空代码块也不允许

# 第一步:继承Shape类(先定义空类)class Shape:    pass# Python的构造方法只有__init__,且第一个参数必须是selfclass Square(Shape):    # 核心构造方法:显式声明self,初始化属性    def __init__(self, x, y, side):        self.x = x  # self等价于Java的this,但必须显式写        self.y = y        self.side = side# 创建实例:无需new关键字s1 = Square(1, 3, 10)s2 = Square(x=1, y=3, side=10)  # 还支持关键字参数,Java没有这个特性

那么Java里的第二个构造方法(4个参数)怎么实现?Python用@classmethod装饰器来做工厂方法:

@classmethoddef make_square_from_points(cls, x1, y1, x2, y2):    if abs(x2 - x1) != abs(y2 - y1):        raise ValueError("Square must have equal sides")    return cls(x1, y1, abs(x2 - x1))  # cls等价于类本身,对应Java的Square

Java通过public/protected/private严格控制访问权限,但python没有强制封装,约定俗成的以_开头的属性/方法视为私有,但它并不是真正的禁止访问,双下划线__开头会触发名词改写

class Square(Shape):    def __init__(self, x, y, side):        self._x = x  # 约定为私有属性        self._y = y        self.__side = side  # 名称改写,外部无法直接通过__side访问# 外部仍能访问(只是不推荐)sq = Square(1,2,3)print(sq._x)  # 能输出1# print(sq.__side)  # 报错print(sq._Square__side)  # 仍能通过改写后的名称访问

Java用toString()返回对象字符串,python则分两个方法,__str__ 面向用户的友好字符串,__repr__面向开发者的字符串

class Square(Shape):    # ... 其他代码 ...    def __str__(self):        return f"Square [x={self._x}, y={self._y}, side={self.__side}]"    def __repr__(self):        return f"Square({self._x}, {self._y}, {self.__side})"sq = Square(5,5,10)print(sq)  # 输出__str__的结果:Square [x=5, y=5, side=10]print(repr(sq))  # 输出__repr__的结果:Square(5,5,10)

需要注意的是Python中字符串拼接不会自动调用__str__,必须显示转换:

# print(sq + ".")  # 报错:不能拼接对象和字符串print(str(sq) + ".")  # 正确:Square [x=5, y=5, side=10].

对于异常方法,Java用throw抛异常,python用raise,还能自定义异常类:

# 自定义异常(继承ValueError)class MalformedSquareException(ValueError):    def __init__(self, x1, y1, x2, y2):        self.x1 = x1        self.y1 = y1        self.x2 = x2        self.y2 = y2    def __str__(self):        return f"点({self.x1},{self.y1})和({self.x2},{self.y2})无法构成正方形"# 使用自定义异常@classmethoddef make_square_from_points(cls, x1, y1, x2, y2):    if abs(x2 - x1) != abs(y2 - y1):        raise MalformedSquareException(x1, y1, x2, y2)    return cls(x1, y1, abs(x2 - x1))# 捕获异常try:    sq = Square.make_square_from_points(4,5,7,11)except MalformedSquareException as e:    print(e)  # 输出:点(4,5)和(7,11)无法构成正方形

对于抽象,Java用abstract关键字定义,python需要导入abc模块实现:

import abc# 定义抽象类(两种方式二选一)class Shape(metaclass=abc.ABCMeta):    # 抽象方法:必须实现,且需要有方法体(用...占位)    @abc.abstractmethod    def area(self):        ...    @abc.abstractmethod    def perimeter(self):        ...    # Python还支持静态抽象方法(Java没有这个概念)    @staticmethod    @abc.abstractmethod    def nb_sides():        ...# 实现抽象类class Square(Shape):    # ... 其他代码 ...    def area(self):        return self.__side * self.__side    def perimeter(self):        return 4 * self.__side    @staticmethod    def nb_sides():        return 4

另一个点,Java仅支持字符串+重载,而Python可以重载几乎所有运算符(__mul__、__lt__、__gt__等):

class Square(Shape):    # ... 其他代码 ...    # 重载*:sq * 3 表示边长放大√3倍    def __mul__(self, n):        return Square(self._x, self._y, self.__side * math.sqrt(n))    # 重载<:比较边长大小    def __lt__(self, other):        return self.__side < other.__side    # 重载>:比较边长大小    def __gt__(self, other):        return self.__side > other.__side# 使用重载的运算符s1 = Square(0,0,10)s2 = s1 * 3  # 调用__mul__print(s1 < s2)  # True,调用__lt__

最后,Python 的 OOP 看似 “松散”,没有 Java 那么多严格的语法约束,但其实是用 “约定优于配置” 的思路,兼顾了灵活性和可读性。对于 Java 开发者来说,不用纠结 “为什么 Python 没有 private”,而是要理解 Python 的设计模式。

最新文章

随机文章