当谈到面向对象编程的特性时,继承(Inheritance),封装(Encapsulation)和多态(Polymorphism)是三个核心概念。下面我将为每个概念提供一个简单的示例来说明它们的作用:
- 继承(Inheritance): 继承允许我们创建一个新的类,并从现有的类中派生出新类,新类将继承原始类的属性和方法。这种关系称为父类和子类的关系,子类可以通过继承来获得父类的特征。
# 定义一个名为 Animal 的父类
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
pass
# 定义一个名为 Dog 的子类,继承自 Animal
class Dog(Animal):
def speak(self):
return "Woof!"
# 定义一个名为 Cat 的子类,继承自 Animal
class Cat(Animal):
def speak(self):
return "Meow!"
# 创建一个 Dog 对象和一个 Cat 对象
my_dog = Dog("Buddy")
my_cat = Cat("Whiskers")
# 调用子类的方法
print(my_dog.speak()) # 输出: Woof!
print(my_cat.speak()) # 输出: Meow!
在上述代码中,我们定义了一个父类 Animal
,并在其中定义了一个 speak
方法。然后我们创建了两个子类 Dog
和 Cat
,它们继承了 Animal
父类的属性和方法。子类可以根据需要重写或扩展继承来的方法。
封装(Encapsulation): 封装是指将相关的数据和方法组合在一个单独的单元中,例如类。通过封装,我们可以限制对数据和方法的直接访问,并提供公共的接口进行访问和操作。
# 定义一个名为 Person 的类,封装了姓名和年龄
class Person:
def __init__(self, name, age):
self._name = name # 使用一个下划线前缀表示属性为受保护的
self._age = age
def get_name(self):
return self._name
def get_age(self):
return self._age
def set_age(self, age):
if age >= 0:
self._age = age
# 创建一个 Person 对象
my_person = Person("Alice", 25)
# 使用公共接口获取和设置属性值
print(my_person.get_name()) # 输出: Alice
print(my_person.get_age()) # 输出: 25
my_person.set_age(30)
print(my_person.get_age()) # 输出: 30
在上述代码中,我们定义了一个 Person
类,并在其中封装了姓名和年龄属性。这些属性使用一个下划线前缀 _
表示为受保护的属性,意味着它们不应该被直接访问。取而代之的是,我们提供了公共的方法 get_name
和 get_age
来获取属性值,并提供了一个公共的方法 set_age
来设置年龄值。
多态(Polymorphism): 多态允许不同的对象对于同一消息作出不同的响应。也就是说,父类的引用可以指向不同的子类对象,并且根据具体的对象类型来调用相应的方法。
# 定义一个名为 Person 的类,封装了姓名和年龄
class Person:
def __init__(self, name, age):
self._name = name # 使用一个下划线前缀表示属性为受保护的
self._age = age
def get_name(self):
return self._name
def get_age(self):
return self._age
def set_age(self, age):
if age >= 0:
self._age = age
# 创建一个 Person 对象
my_person = Person("Alice", 25)
# 使用公共接口获取和设置属性值
print(my_person.get_name()) # 输出: Alice
print(my_person.get_age()) # 输出: 25
my_person.set_age(30)
print(my_person.get_age()) # 输出: 30
在上述代码中,我们定义了一个父类 Shape
,其中包含了一个计算面积的方法。然后我们创建了两个子类 Rectangle
和 Circle
,它们分别重写了父类的 calculate_area
方法来计算不同形状的面积。
我们将这些子类对象添加到一个 shapes
列表中,然后使用多态性质,通过遍历列表来调用相同的 calculate_area
方法。由于每个子类都提供了自己的具体实现,所以在循环中调用 calculate_area
方法时,会根据对象类型调用相应的子类方法。