# 第 3-2 课课堂练习:Python 与 Java 的封装差异 # # 关键规则已经写进每部分题目,可以不先完整阅读讲义。 # 请保留题目、预期结果和自查说明,并独立完成 Product 类。 # 第一部分:定义 Product 类和初始化方法 # 1. 定义 __init__(self, name, price) 方法。 # 2. name 标注为 str,price 标注为 float,返回值标注可自行决定是否添加。 # 3. 使用 self._name = name 保存名称。 # 4. 使用 self.__price = 0.0 建立双下划线属性。 # 5. 最后执行 self.price = price,通过后面定义的 setter 完成初始价格校验。 # # Java 对照提醒: # - _name 只表示“内部使用”的约定,外部访问不会产生语法错误; # - __price 会触发名称改写,但不等于 Java 的强制 private; # - 双下划线不能作为保存密码等敏感信息的安全措施。 # 第二部分:为 name 定义只读 property # 1. 在方法上方添加 @property。 # 2. 定义 name(self) 方法并返回 self._name。 # 3. 不要定义 @name.setter,使调用者不能通过 product.name = ... 正常修改名称。 # # Java 对照提醒: # - Java 常写 getName();Python 调用时直接写 product.name; # - 虽然调用形式像字段,但实际上会执行 name() 方法。 # 第三部分:为 price 定义可读写 property # 1. 使用 @property 定义 price(self),返回 self.__price。 # 2. 使用 @price.setter 定义同名方法 price(self, value)。 # 3. value 标注为 float。 # 4. value 小于 0 时执行 raise ValueError("价格不能小于 0。")。 # 5. 校验通过后执行 self.__price = value。 # # Java 对照提醒: # - 这相当于 getPrice() 和 setPrice(),但调用形式仍是 product.price; # - 不要同时保留公开的 price 实例属性,否则会和 property 的职责混淆。 # 第四部分:定义 discount(self, rate) 实例方法 # 1. rate 标注为 float。 # 2. rate 必须满足 0 <= rate <= 1,否则抛出 ValueError("折扣率必须在 0 到 1 之间。")。 # 3. 合法时执行 self.price = self.price * rate。 # 4. 通过 property 修改价格,复用统一的价格入口。 # 第五部分:定义 main() 并验证行为 # 1. 创建 Product("机械键盘", 500.0)。 # 2. 输出“商品:机械键盘|价格:500.0 元”。 # 3. 执行 product.price = 450.0,再输出“修改后价格:450.0 元”。 # 4. 执行 product.discount(0.8),再输出“折扣后价格:360.0 元”。 # 5. 使用 try...except 测试 product.price = -1.0。 # 6. 捕获 ValueError 后输出“非法价格已被阻止:价格不能小于 0。”。 # 7. 添加程序入口判断并调用 main()。 # # 预期输出: # 商品:机械键盘|价格:500.0 元 # 修改后价格:450.0 元 # 折扣后价格:360.0 元 # 非法价格已被阻止:价格不能小于 0。 # 完成后自查: # 1. 是否知道单下划线只是内部使用约定; # 2. 是否知道双下划线会名称改写,但不是绝对私有; # 3. 是否能用 @property 代替简单的 Java getter; # 4. 是否能用 @属性名.setter 在赋值时执行校验; # 5. 是否能说明 product.price 看似访问字段、实际会执行方法; # 6. 是否只把运行错误和逻辑错误视为阻塞项,不把可选类型注解当作必须项。