介绍
所谓对象是指类对象,那么什么是类呢?
类,是事物的具体描述,xxx类型,是抽象的。 而对象,是类实例化后产生出的产物。个人见解:
可以把类看出图纸,而对象就是你靠图纸打造出来的东西。
构造
首先,先造一个类和对象出来吧!
- Animal是类名,你可以任选的,记得大写哦。括号里是Animal类的父类,如果是object那么可以不写。
- cat是根据Animal类的描述实例化出的一个对象,对象名要小写,不可冲突,可以根据类实例出多个Animal类的对象。
# Animal类
class Animal(object): # 父类是object
def __init__(self):
pass
# cat是Animal类对象
cat = Animal()
- init,特殊方法init负责实例化类以及传参,类中方法必带的参数self指的是类实例本身,self是不用传参的。
class Animal:
def __init__(self, name):
print("动物叫", name)
print("hhh")
cat = Animal("阿猫")
# 动物叫 阿猫
# hhh
如果类里面什么都不写,那么构造其实毫无意义,我们创造出一个类是希望将一些方法和变量放进去,这样当需要某些方法的时候不需要再重建方法,直接调用这个类对象中的方法。
class Animal:
def __init__(self, name):
self.name = name
def eat(self):
print(self.name, "要吃东西")
cat = Animal("阿猫")
cat.eat() # 阿猫 要吃东西
print("动物是", cat.name) # 动物是 阿猫
看上面的示例,会发现我们很容易从外部取参,传参。外部可以直接操纵我们类中的变量,这样怎么行。所以我们要加上限制,在我们name变量前加_,这样_name变量是私有变量,无法直接获取。根据于此,需要通过get、set方法间接操控类中的变量。
class Animal:
def __init__(self):
pass
def eat(self):
print(self._name, "要吃东西")
def getName(self):
return self._name
def setName(self, name):
self._name = name
cat = Animal()
cat.setName("阿猫")
cat.eat() # 阿猫 要吃东西
print("动物是", cat.getName()) # 动物是 阿猫
像这样,将变量和方法像一个密闭的盒子一样打包起来,只能从盒子提供的接口(只是抽象意义的)操控盒子的例子,也是面向对象的特性之一:封装。
继承
- python中万物皆是对象,它们都继承于object。讲到继承,就必须说说为什么会有继承。
如果我要写一个Cat类,Cat类有很多方法。又要写一个Dog类,Dog类同样也要有很多方法。但是Cat和Dog是有共同点的,比如都有吃东西的方法,那么我可以写一个Animal类,里面有一个方法是吃东西,让Cat和Dog类都继承于Animal(Animal是父,Cat和Dog是子),这样Cat和Dog里面不需要写吃东西的方法,可以直接使用这个方法了。 - 这也看出来父类可以将某些方法和变量抽取出来,为子类而服务。注意:父类有的子类一定会有,子类有的父类不一定有。
class Animal(object):
meat = "肉"
def setName(self, name):
self.name = name
def eat(self):
print(self.name + "吃" + self.meat)
class Dog(Animal):
pass
class Cat(Animal):
pass
cat = Cat()
cat.setName("阿猫")
dog = Dog()
dog.setName("阿狗")
cat.eat()
dog.eat()
# 阿猫吃肉
# 阿狗吃肉
一个类不仅可以继承于另外一个类,还可以多继承多个类。这个和java有点不一样哈。
class Cat(Animal,Dog):
pass
cat如果不想只是“吃肉”。cat还想吃鱼,dog还想啃骨头,那么可以重写eat方法。注意:重写是对于子类而言的。
class Dog(Animal):
def eat(self):
print(self.name + "啃骨头")
class Cat(Animal):
def eat(self):
print(self.name + "吃鱼儿")
cat = Cat()
cat.setName("阿猫")
dog = Dog()
dog.setName("阿狗")
cat.eat()
dog.eat()
# 阿猫吃鱼儿
# 阿狗啃骨头
多态
多态就是一个类有多种表现形式。多态必须要通过子类对父类之间的重写达成。
def aeat(animal):
print(type(animal))
animal.eat()
cat = Cat()
cat.setName("阿猫")
dog = Dog()
dog.setName("阿狗")
animal=Animal()
animal.setName("动物")
aeat(animal)
aeat(dog)
aeat(cat)
'''
<class '__main__.Animal'>
动物吃肉
<class '__main__.Dog'>
阿狗吃肉
<class '__main__.Cat'>
阿猫吃鱼儿
'''
-
在示例中希望表达的意思就是aeat方法要求的参数是Animal类型,可是也可以传入其子类,并且通过重写eat方法改变了父类的表达。
-
其实阿猫和阿狗都是可以看作动物的,阿狗没有重写方法自然实现了动物的方法。而阿猫重写了方法,给予了新的表现状态。
-
多态的概念中,子类可以看作是父类,但是父类不能看作子类的。如:某方法要求传入Cat类,则不能传入Animal类。反之则可以。
-
如果以本案例做实验则上面的案例却是可以实现的。这是因为python的不严谨,如果是java的上面父类是不能当做子类传参的。但是,在python中以案例中的aeat为例,只要你满足传入对象可以实现eat方法就可以传入。所以需要进行判断和审核。
判断:
cat = Cat()
cat.setName("阿猫")
print(isinstance(cat,Animal)) # True
print(type(cat)) # <class '__main__.Cat'>
总结
说真的,写到多态的时候真觉得python这边很不适应,更喜欢java的严谨。