面向对象的编程带来的主要好处之一是代码的复用,实现这种复用的方法之一是通过继承机制。

python中解决代码复用的方式:继承和组合。

1 什么是继承

继承是一种创建类的方法,在python中,一个类可以继承来自一个或多个父类。原始类称为基类或超类。

class ParentClass1: #定义父类

pass

class ParentClass2: #定义父类

pass

class SubClass1(ParentClass1): #单继承,基类是ParentClass1,派生类是SubClass

pass

class SubClass2(ParentClass1,ParentClass2): #python支持多继承,用逗号分隔开多个继承的类

pass

查看继承:

>>> SubClass2.__bases__

(, )

1.1 什么时候用继承

假如已经有几个类,而类与类之间有共同的变量属性和函数属性,那就可以把这几个变量属性和函数属性提取出来作为基类的属性。而特殊的变量属性和函数属性,则在本类中定义,这样只需要继承这个基类,就可以访问基类的变量属性和函数属性。可以提高代码的可扩展性。

1.2 继承和抽象(先抽象再继承)

抽象即提取类似的部分。

基类就是抽象多个类共同的属性得到的一个类。

class Riven:

camp='Noxus'

def __init__(self,nickname,

script,

aggressivity=54,

life_value=414,

):

self.nickname = nickname

self.aggressivity = aggressivity

self.life_value = life_value

self.script=script

def attack(self,enemy):

print(self.script)

enemy.life_value -= self.aggressivity

class Garen:

camp='Demacia'

def __init__(self,nickname,

script,

aggressivity=58,

life_value=455,

):

self.nickname = nickname

self.aggressivity = aggressivity

self.life_value = life_value

self.script = script

def attack(self,enemy):

print(self.script)

enemy.life_value -= self.aggressivity

g1=Garen("德玛西亚之力","人在塔在")

g1.camp="诺克萨斯"

r1=Riven("瑞雯","断剑重铸之日,骑士归来之时")

g1.attack(r1)

print(r1.life_value)

结果:

人在塔在

356

Garen类和Riven类都有nickname、aggressivity、life_value、script四个变量属性和attack()函数属性,这里可以抽象出一个Hero类,里面有里面包含这些属性。

class Hero:

def __init__(self, nickname,

script,

aggressivity,

life_value,

):

self.nickname = nickname

self.aggressivity = aggressivity

self.life_value = life_value

self.script = script

def attack(self,enemy):

print("Hero.attack")

enemy.life_value -= self.aggressivity

class Riven(Hero):

camp='Noxus'

def __init__(self,nickname,script,aggressivity=54,life_value=414):

Hero.__init__(self,nickname,script,aggressivity,life_value)

def attack(self,enemy):

print(self.script)

Hero.attack(self,enemy)

class Garen(Hero):

camp='Demacia'

def __init__(self,nickname,script,aggressivity=58,life_value=455):

Hero.__init__(self, nickname, script, aggressivity, life_value)

def attack(self,enemy):

print(self.script)

Hero.attack(self, enemy)

g1=Garen("德玛西亚之力","人在塔在")

g1.camp="诺克萨斯"

r1=Riven("瑞雯","断剑重铸之日,骑士归来之时")

g1.attack(r1)

print(r1.life_value)

结果:

人在塔在

Hero.attack

356

严格来说,上述Hero.init(self,...),不能算作子类调用父类的方法。因为我们如果去掉(Hero)这个继承关系,代码仍能得到预期的结果。

总结python中继承的特点:

1. 在子类中,并不会自动调用基类的__init__(),需要在派生类中手动调用。

2. 在调用基类的方法时,需要加上基类的类名前缀,且需要带上self参数变量。

3. 先在本类中查找调用的方法,找不到才去基类中找。

1.3 继承的好处

提高代码的复用。

1.4 继承的弊端

可能特殊的本类又有其他特殊的地方,又会定义一个类,其下也可能再定义类,这样就会造成继承的那条线越来越长,使用继承的话,任何一点小的变化也需要重新定义一个类,很容易引起类的爆炸式增长,产生一大堆有着细微不同的子类. 所以有个“多用组合少用继承”的原则。

# 2 什么是派生      派生就是子类在继承父类的基础上衍生出新的属性。子类中独有的,父类中没有的;或子类定义与父类重名的东西。子类也叫派生类。

3 组合

代码复用的重要的方式除了继承,还有组合。

组合,在一个类中以另一个类的对象作为数据属性,称为类的组合。

class Skill:

def fire(self):

print("release Fire skill")

class Riven:

camp='Noxus'

def __init__(self,nickname):

self.nickname=nickname

self.skill5=Skill().fire()#Skill类产生一个对象,并调用fire()方法,赋值给实例的skill5属性

r1=Riven("瑞雯")

结果:

release Fire skill

# 4 组合和继承的使用场景

继承的方式

通过继承建立了派生类与基类之间的关系,它是一种'是'的关系,比如白马是马,人是动物。

class Animal:

def walk(self):

print("Animal is walking")

def eat(self):

print("Animal is eating")

class Person(Animal):

pass

p1=Person()

p1.walk() #Animal is walking

组合的方式

用组合的方式建立了类与组合的类之间的关系,它是一种‘有’的关系,比如老师有生日,老师教python课程。

class Teacher:

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

self.name=name

self.sex=sex

self.course = course

class Course:

def __init__(self, name, period):

self.name = name

self.period = period

co=Course("python","7 m")

t1=Teacher("zhang","male",co)

print(t1.course.name)

结果:

python

当类之间有显著不同,并且较小的类是较大的类所需要的组件时,用组合比较好。

5 接口和归一化设计

什么是接口?接口就是对外只提供抽象的方法的集合。

继承的两种用途:

继承基类的方法,并且做出自己的改变或者扩展(代码复用)

声明某个子类兼容于某基类,定义一个接口类Interface,接口类中定义了一些接口名(就是函数名)且并未实现接口的功能,子类继承接口类,并且实现接口中的功能。

class Interface:#定义接口Interface类来模仿接口的概念,python中没有interface关键字来定义一个接口。

def read(self): #定接口函数read

pass

#raise AttributeError("read function must be implemented") #如果不重写read函数就报错

def write(self): #定义接口函数write

pass

#raise AttributeError("wirte function must be implemented") #如果不重写write函数就报错

class Txt(Interface): #文本,具体实现read和write

def read(self):

print('文本数据的读取方法')

def write(self):

print('文本数据的读取方法')

class Sata(Interface): #磁盘,具体实现read和write

def read(self):

print('硬盘数据的读取方法')

def write(self):

print('硬盘数据的读取方法')

实践中,继承的第一种含义意义并不很大,甚至常常是有害的。因为它使得子类与基类出现强耦合。

继承的第二种含义非常重要。它又叫“接口继承”。

接口继承实质上是要求“做出一个良好的抽象,这个抽象规定了一个兼容接口,使得外部调用者无需关心具体细节,可一视同仁的处理实现了特定接口的所有对象”——这在程序设计上,叫做归一化。

归一化使得高层的外部使用者可以不加区分的处理所有接口兼容的对象集合——就好象linux的泛文件概念一样,所有东西都可以当文件处理,不必关心它是内存、磁盘、网络还是屏幕(当然,对底层设计者,当然也可以区分出“字符设备”和“块设备”,然后做出针对性的设计:细致到什么程度,视需求而定)。

6 抽象类

6.1 什么是抽象类

与java一样,python也有抽象类的概念,但是需要借助模块实现。抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化。

抽象类与普通类的不同之处在于:抽象类中只能有抽象方法(没有实现功能),该类不能被实例化,只能被继承,且子类必须实现抽象方法。

class Interface(metaclass=abc.ABCMeta): # 定义接口Interface类来模仿接口的概念,python中没有interface关键字来定义一个接口。

@abc.abstractclassmethod

def read(self): # 定接口函数read

pass

@abc.abstractclassmethod

def write(self): # 定义接口函数write

pass

class Txt(Interface): # 文本,具体实现read和write

def read(self):

print('文本数据的读取方法')

def write(self):

print('文本数据的读取方法')

class Sata(Interface): # 磁盘,具体实现read和write

def read(self):

print('硬盘数据的读取方法')

def write(self):

print('硬盘数据的读取方法')

6.2 抽象类与接口

抽象类的本质还是类,抽象类的本质还是类,指的是一组类的相似性,包括数据属性(如all_type)和函数属性(如read、write),而接口只强调函数属性的相似性。

抽象类是一个介于类和接口直接的一个概念,同时具备类和接口的部分特性,可以用来实现归一化设计 。

类的继承和派生java_python 类的继承和派生相关推荐

  1. 类的继承和派生java_类的继承和派生

    一.类的继承和派生定义. 继承:保持已有类的特性而构造新类的过程称为继承. 派生:在已有类的基础上新增自己的特性而产生新类的过程称为派生. 被继承的已有类称为基类. 派生出的新类称为派生类. 二.继承 ...

  2. C++中public/private/protected三种继承方式下基类成员对派生类的可见性探讨

     原文: http://blog.csdn.net/zgjxwl/article/details/4804233 1.public继承方式下 #include <iostream>   ...

  3. C++的继承和派生(一)父类和派生类(子类)的介绍以及派生类的访问控制

    在介绍继承和派生之前,先看下面一段代码 class Student1 {public:int m_socre;int m_age;void speak() {cout << "S ...

  4. C++ 类继承:构造函数与析构函数调用顺序,派生类和基类之间的特殊关系,公有继承及其他

    文章目录 一.派生类构造函数与基类构造函数 二.创建与销毁派生类对象时,构造函数和析构函数的调用 三.派生类和基类之间的特殊关系 四.公有继承 (一).何为公有继承 (二).多态公有继承 (三).虚函 ...

  5. 【C++】继承和派生、虚继承和虚基类、虚基类表和虚基类指针

    继承和派生.虚继承和虚基类.虚基类表和虚基类指针 继承和派生 继承概述 继承基本概念 派生类中的成员 继承的内容 派生类定义 派生类访问控制 对象构造和析构 对象构造和析构的调用顺序 继承中的构造和析 ...

  6. java 枚举的继承_java中枚举类可以被继承吗?

    java 枚举类 java中,使用关键字enum来定义枚举类,枚举类是一个特殊的类,大部分功能和普通类是一样的,区别为: ● 枚举类继承了java.lang.Enum类,而不是默认的Object类.而 ...

  7. C++中的虚继承与虚基类

    1.Cpp中的虚继承与虚基类 在多继承时,很容易产生命名冲突的问题,即使我们很小心地将所有类中的成员变量和成员函数都命名为不同的名字,命名冲突依然有可能发生,比如典型的是菱形继承,如下图所示: 类A派 ...

  8. python中的继承有什么特点_python类的继承是什么?类的继承有什么样的规则?

    在这篇文章之中我们来了解一下python类的继承,对于刚刚接触到python这一编程语言的朋友来说,对于python类的继承的了解应该比较少,不过没关系,在接下来的文章之中我们就来了解一下python ...

  9. C++虚继承和虚基类详解(二)

    虚继承(Virtual Inheritance) 为了解决多继承时的命名冲突和冗余数据问题,C++ 提出了虚继承,使得在派生类中只保留一份间接基类的成员. 在继承方式前面加上 virtual 关键字就 ...

最新文章

  1. 坚持使用GNU/Linux
  2. Linux远程管理协议相关知识介绍
  3. linux上的那些查找的命令
  4. [dp]Leetcode 5. Longest Palindromic Substring
  5. 用python祝福父亲节_父亲节给爸爸的祝福语微信48条
  6. python面试题No2
  7. 游戏本自动掉帧_机 · 科普帖丨如何在夏天告别游戏掉帧的问题
  8. 用友U8自定义按钮开发
  9. 爱了爱了!阿米洛熊猫机械键盘cherry樱桃粉轴白灯,写代码神器!免费包邮送到家!...
  10. 编程界的修仙秘籍《JavaScript》百炼成仙第1章
  11. 怎样用美图秀秀制作一寸照片
  12. MySQL报错:The server quit without updating PID file 我的解决思路和方法
  13. 织梦建站教程:文章列表隔行换色 隔5行横线
  14. Navicat Premium 15导入excel表格
  15. 纪念特洛伊英雄 Sinon - SAP UI5 Mock Server 使用步骤和工作原理介绍
  16. 网站优化十大方法之关键字篇
  17. Linux中一些最优秀的浏览器
  18. vc 6.0++解决兼容性及闪退问题
  19. 【BX学习之常用网址】 开发常用网址
  20. 新版标准日本语初级_第四课

热门文章

  1. 美博士除甲醛告诉你室内环保多重要
  2. 在线能力测试题资源汇总
  3. Solidworks Motion 运动仿真视频教程
  4. 近期对FTP及Excel数据处理的一些摸索
  5. 阿里云自主研发云原生数据库POLARDB的开拓之路
  6. PostgreSQL命令接口
  7. 29 - 打家劫舍问题
  8. 台式计算机默认关机变注销,Win7关机变注销怎么办 Win7点击关机变成注销现象的解决方法...
  9. 关于联想y485p装win10显卡驱动问题
  10. 校招内卷实况:985211的秋招,从春天开始