类和目的,基础巩固
PHP继承
这是一篇迟来的换代,因为它应有在前两日就被更新了,但是由于自家匈牙利(Magyarország)语四级没过!没过!没过!导致自家心情低沉,所以就玩了几天的娱乐,哦不,进行了几天反思,痛定思痛
痛何如哉!
以下都是自身个人的知道,有错的地点还望不吝赐教。
缘何须要三番五次?
接轨就是 一个子类通过extends父类把父类的属性和章程继承下来。
借使现在现今内需写多个类,小学生类和高中生类,小学生会说话,走路,考试,高中生也会讲话走路,考试,那么只要你写两次说话,走路,考试,那么就会展现臃肿,管理起来也会麻烦很多,即使定义一个类叫做学生类富含说话,走路,考试,然后让小学生类和高中生类来继承那几个学生类就会展现好广大,比如这样。
<?php
class student{
function speak(){
echo '说话';
}
function walk(){
echo '走路';
}
function test(){
echo '考试';
}
}
class pupil extends student{
function test(){
echo '小学生考试';
}
}
class senior extends student{
function test(){
echo '高中生考试';
}
}
$pupil=new pupil();
$pupil->speak();
$pupil->walk();
$pupil->test();
echo '<br />';
$senior=new senior();
$senior->speak();
$senior->walk();
$senior->test();
?>
输出:
说话走路小学生考试
说话走路高中生考试
诸如此类代码管理起来就会好过多。
一旦现在小学生要读书一个新的技术吃东西,我今日这么写。
<?php
class student{
function speak(){
echo '说话';
}
function walk(){
echo '走路';
}
function test(){
echo '考试';
}
}
class skill{
function eat(){
echo '吃东西';
}
}
class pupil extends student,skill{
function test(){
echo '小学生考试';
}
}
$pupil=new pupil();
$pupil->speak();
$pupil->walk();
$pupil->test();
$pupil->eat();
?>
如若如此写,那么就会报错:
Fatal error: Class 'studentskill' not found in D:\xampp\htdocs\1.php on line 18
因为php中是无法那样完成多三番一回的,要是想要达成多连续可以这么写:
<?php
class student{
function speak(){
echo '说话';
}
function walk(){
echo '走路';
}
function test(){
echo '考试';
}
}
class skill extends student{
function eat(){
echo '吃东西';
}
}
class pupil extends skill{
function test(){
echo '小学生考试';
}
}
$pupil=new pupil();
$pupil->speak();
$pupil->walk();
$pupil->test();
$pupil->eat();
?>
输出:
说话走路小学生考试吃东西
先用一个skill类继承student类,然后再用pupil类继承skill类,那样就相当于pupil类继承了student类和skill类。
格局重写
bf88必发唯一官网 ,一经要促成的八个类有一道特性,那么就足以将以此合伙的表征抽象出一个父类。
比如,有小学生类和中学生类,那样的多少个类,他们都是学员,那么就可以抽象出一个学员类,学生都会考查,那么就把试验那些点子写在学生这么些类里面。
那就是说难点就是,小学生是小学生的试验,中学生是中学生的考查,我无法都输出考试,那里就用到了艺术重写。
在子类中定义一个与父类一样的办法,那样实践的时候,父类中的方法就会被遮盖,从而输出的只有子类中定义的法门。
举例:
<?php
class student{
function test(){
echo '考试';
}
}
class pupil extends student{
function test(){
echo '小学生考试';
}
}
class senior extends student{
function test(){
echo '中学生考试';
}
}
$pupil=new pupil();
$pupil->test();
echo '<br />';
$senior=new senior();
$senior->test();
?>
输出:
小学生考试
中学生考试
多态的落到实处有3种方法:
类和目的,基础巩固。类和目的的定义
面向对象编程最要害的定义就是类和目的,类集合了颇具目的的静态特征和动态特征,是目的的蓝图和模板,有了类就足以制造对象。所以类是抽象的,对象是现实性的。如人是一个类,你,我,他就是属于人这几个类的多个具体的靶子。
对象的4个特征:
1.一体皆为对象
2.每一个对象都是绝世的
3.目的可以归入某个类
4.对象是由类创立出来的,是有血有肉的
多态
若果要简明的叙说多态的话,我个人是如此敞亮的:经过持续,父类定义方法,具休的兑现由子类举办。
1、类的后续(虚方法) ; 2、抽象类; 3、接口
定义类和创制对象
- 类和目的,基础巩固。#### 定义类
定义类须求做两件事:数据抽象和作为抽象
数据抽象:抽取对象的一块儿的静态特征,称为属性;
行事抽象:抽取对象的联合的动态特征,称为方法。
如定义一个类为学生,学生的属性包罗:姓名、年龄等,学生的一颦一笑包括:上课、考试等。
定义类的格式:class
类名(类的父类),注意:类名的命名选取驼峰命名法,每个单词的首字母大写。如下:
class Student(object): # object - Student是object的子类
pass
概念属性:
用构造方法(构造器/构造子 – constructor)设定属性,如下:
def __init__(self, name, age): # 也可为属性设置默认值,方法和函数相同
# 给对象绑定属性(name, age)
self.-name = name
# self.__name = name 在属性名称前面加2个下划线 - 把这个属性隐藏起来,理论上值不能被修改,但可以通过其他方法修改
# self.name = name
self.-age = age
在创制对象时,就要求调用构造方法,给目的的品质赋值,所以调用构造方法不是平素选取情势的名字,而是从来选取类的名字。如下:
stu1 = Student('文文', 16)
定义方法:
在类里面的函数称为一种格局,方法是其一类生成的目标的一举一动。大家定义一个格局就象征对象可以吸纳那个信息。对象的法门的率先个参数都统一写成self,它表示了收纳新闻的靶子。如下:
def study(self, course): # self代表正在接收消息的对象
print('%s正在学习%s' % (self.name, course))
def test(self):
print('正在参加考试')
调用方法的格式 :对象.信息(参数)
,只传self后的参数,因为对象就是self。如下:
stu1.study('Python')
stu2.test()
- #### 创造对象
调用构造方法创立对象,实际上调用的是Student类中的 _init_ 方法
成立对象的格式:对象名称 = 类名(属性值)
stu1 = Student('文文', 16)
01代码
//父类
class Person
{
public virtual void skill() //vitrual -虚方法,方法可被重写
{
Console.WriteLine("人会走路");
}
}
class Xiaoming:Person
{
public override void skill() //重写父类方法
{
Console.WriteLine("小明会唱歌");
}
}
class XiaoHu : Person
{
public override void skill()
{
Console.WriteLine("小虎会游泳");
}
}
class Program
{
static void Main(string[] args)
{
Person p1 = new Xiaoming();//里氏转换原则 可以将子类赋值给父类
Person p2 = new XiaoHu();
p1.skill();
p2.skill();
Console.ReadKey();
}
}
输出:
通过这一个事例 Person 类定义了skill方法,方法的具体落到实处由子类举办。
1、类的接轨
实例
用面向对象的想想写程序的进度就是指给目标发一个音讯,只要对象吸收到那么些音信,就会活动落成那一个行为。要做到这几个顺序有3个步骤:
1.定义类
2.调用构造方法,创设对象
3.给目标发出音讯:通过给目的发音讯,让对象已毕某些工作。给目的发音信其实就是指调用行为
02比方不重写的话
即 若是子类的 override 改为new
那么父类和子类的点子是独自的,此时举办下边的代码
//父类
class Person
{
public virtual void skill()
{
Console.WriteLine("人会走路");
}
}
class Xiaoming:Person
{
public new void skill() //重写父类方法
{
Console.WriteLine("小明会唱歌");
}
}
class Program
{
static void Main(string[] args)
{
Person p1 = new Xiaoming();//里氏转原则
Xiaoming p2 = new Xiaoming();
p1.skill();
p2.skill();
Console.ReadKey();
}
}
输出:
可以看出,p.skill();那里看.前面的靶子,是怎样类型的,就执行那么些类里里面的
skill()方法,这里P1是Person类的,P2是Xiaoming类的。
持续与里氏转换协作使用也足以完结多态的。在那边大约讲一下里氏转换:a.子类的对象足以隐式转换成父类的目标。例:
Student(子类) st=new Student();Person(父类) p=st;
b.把父类的对象强转成子类的对象。例:Student st=(Student)p;
使用通过持续和里氏转换也落实一个对象表现出各类意况。
->虚方法:子类中对某一个艺术超过半数如出一辙,个别分化,在父类中定义虚方法,一样的用持续的,不均等的重写。
宪章数字时钟
import time
# 定义类
class Clock(object):
def __init__(self, hour=0, minute=0, second=0):
self._hour = hour
self._minute = minute
self._second = second
def run(self):
"""走字"""
self._second += 1
if self._second == 60:
self._second = 0
self._minute += 1
if self._minute == 60:
self._minute = 0
self._hour += 1
if self._hour == 24:
self._hour = 0
def show(self):
return '%02d : %02d : %02d' % (self._hour, self._minute, self._second)
# 下面的方法可以获取对象的字符串表示形式
# 当我们用print打印对象时会自动调用该方法
# print(clock1)
def __str__(self):
return '%02d : %02d : %02d' % (self._hour, self._minute, self._second)
def main():
# 创建对象
clock1 = Clock(1, 4, 49) # 若此处不给属性赋值,则使用默认值
while True:
# 调用行为
print(clock1.show())
time.sleep(1)
# 调用行为
clock1.run()
if __name__ == '__main__':
main()
多态+不难工厂
若是我想经过输入 小明,小虎。
那时候系统自动给彰显小明会什么,小虎会什么出来。
->例子:假诺所有的人都会走路,并且半数以上人都是用2条腿走,唯有个旁人比如老人(3条腿)、残疾人,所以行进定义在人类中,正常人类的子类
都用父类的行走方法继承就行了,特殊子类如老人类可以重写走路的点子
类的再而三
继承是从已经局地类创制新类的历程,提供后续音讯的号称父类 / 超类 /
基类,得到继续音信的称呼子类/派生类/衍生类,通过一而再我们可以将子类中的重复代码抽取到父类中,子类通过持续并复用那个代码来减弱重复代码的编写,未来一旦要有限支撑子类的国有代码,只必要在父类中展开操作即可。
- ### 子类继承一个父类
子类可以由此调用父类开首化的法子,继承父类的习性
# B继承A
class A(object):
def __init__(self, name):
self._name = name
class B(A):
def __init__(self, name, age):
super().__init__(name)
self._age = age
子类可以三番五次父类的表现(方法),也得以对章程举行重写 / 覆盖 / 置换 /
覆写(override)。方法重写指的是子类在三番五次父类方法之后,对章程举办了再度完结,当我们给子类对象发送执行此措施的新闻时,执行的是子类重新写过的法子。不相同的子类可以完成分化重写的版本。下边举例表达。
class Person(object):
def __init__(self, name, gender):
self._name = name
self._gender = gender
def drink(self):
print('%s正在喝水' % self._name)
class Teacher(Person):
def __init__(self, name, gender, subject):
super().__init__(name, gender)
self._subject = subject
# 老师类对drink方法进行了重写
def drink(self):
print('%s正在喝茶' % self._name)
class Student(Person):
def __init__(self, name, gender, score):
super().__init__(name, gender)
self._score = score
# 学生类对drink方法进行了重写
def drink(self):
print('%s正在喝饮料' % self._name)
def main():
t1 = Teacher('Luo', 'male', 'Python')
s2 = Stident('shu', 'female', '98')
t1.drink
s1.drink
if __name__ == '__main__':
main()
教师和学生多个类都对父类的drink方法举办了重写,并且是例外版本的重写。当给先生对象发drink信息时,老师执行的是喝茶的行为,给学员发送drink信息时,学生实施的时喝饮料的行事。
- ### 子类继承多个父类
假若一个子类继承四个父类,在调用父类起头化方法时要用父类调用。
一旦八个父类有同一个艺术,子类在调用此格局时会默许调用继承时写在最前方的父类的方法。
举例:儿子继承了八个类,如若那三个类都有drink的主意,当孙子调用drink方法时,会自行调用Musicion的drink方法
class Son(Musicion, Father, Monk):
def __init__(self, name, nickname, art_name):
# 调用父类初始化的方法
Father.__init__(self, name)
Monk.__init__(self, nickname)
Musicion.__init__(self, art_name)
def main():
s = Son('洛洛', ‘智障禅师’, 'kiki' )
s.drink
if __name__ == '__main__':
main()
如果子类重写了一个措施,相当于把装有有此方法的父类都重写了。如若父类都有同一个表现,最好把父类设置为抽象类,把办法设置为架空方法,须求子类必须达成.。上面举例表明。
from abc import ABCMeta, abstractmethod
class Father(object, metaclass=ABCMeta):
def __init__(self, name):
self._name = name
@abstractmethod
def drink(self):
pass
class Musicion(object, metaclass=ABCMeta):
def __init__(self, art_name):
self._art_name = art_name
@abstractmethod
def drink(self):
pass
class Monk(object):
def __init__(self, nickname):
self._nickname = nickname
def eat_vagetable(self):
print(self._nickname + '在吃斋')
class Son(Musicion, Father, Monk):
# 继承多个类
# 调用类的构造方法
def __init__(self, name, nickname, art_name):
Father.__init__(self, name)
Monk.__init__(self, nickname)
Musicion.__init__(self, art_name)
# 在子类重写drink方法,相当于把所有有drink方法的父类都重写了
def drink(self):
print(self._name + '在喝果汁')
def main():
son = Son('LI', '智障禅师', 'wen')
# 此处drink方法调用的是Son重写的喝果汁的drink
son.drink()
son.eat_vagetable()
if __name__ == '__main__':
main()
那就是说首先增添一个厂子类
活着中工厂是用来加工的成品的,同样那里也是依据传入的参数,加工后归来对应的结果
方方面面代码
//父类
class Person
{
public virtual void skill()
{
Console.WriteLine("人会走路");
}
}
class Xiaoming:Person //继承Person
{
public override void skill() //重写父类方法
{
Console.WriteLine("小明会唱歌");
}
}
class XiaoHu : Person
{
public override void skill()
{
Console.WriteLine("小虎会游泳");
}
}
//工厂类 --新增
class Factory
{
public static Person instance(string Name)
{
switch (Name)
{
case "1": return new Xiaoming();
case "2":return new XiaoHu();
default: return null;
}
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("请输入序号查看技能,输入1、2....");
Console.WriteLine("1.小明");
Console.WriteLine("2.小虎");
Console.WriteLine("输入:");
string res = Console.ReadLine();
Console.WriteLine("结果:");
Person p = Factory.instance(res);
if (p != null)
{
p.skill();
}
else
{
Console.WriteLine("没找到这个人");
}
Console.ReadKey();
}
}
实施结果:
那时,多态+简单工厂就曾经落到实处了。
->关键字用在何地?
抽象类
Python没有从语言层面援救抽象类的定义,大家得以经过abc(abstract
class)模块来创建抽象类的成效。在定义类的时候经过点名metaclass=ABCMeta可以将类表明为抽象类,抽象类是不能够成立对象的,抽象类存在的意义是专程拿给其他类继承,abc模块中还有一个包装器abstractmethod,通过那几个包装器可以将艺术包装为架空方法,需求子类必须重写该格局
在意:如若抽象类中尚无抽象方法,抽象类如故得以创造对象
展开1:抽象(abstract)完毕多态
1. 前面的 virtual(虚方) 落成多态已经完毕了,其实
抽象(abstract)达成多态也是日照小异
2. abstract 和virtual的区分在于abstract
没有方法体,方法都得以被重写。
达成:把地点完整的代码 的父类改成 下面就完毕了,功能雷同。
//父类
abstract class Person
{
public abstract void skill();//方法没有方法体
}
->new 倘诺子类继承父类,而艺术名又同样,在子类的方式中加new则叫突显隐藏基类方法,没有new则叫隐式隐藏基类方法;若是不看父类,则不知底父类中是还是不是有其一主意,或者子类的办法是或不是是父类的重写和潜伏父类的点子;所以假诺加了new就是父类的隐蔽方法。如若父类中平素不那些格局而又加了new则会警告,那一个方法不会隐藏继承的分子,不必要new关键字。所以在那种情况下new就是一个标志,表示子类是还是不是是隐藏基类方法。
实例
用下边的实例来验证抽象类和办法重写
展开2:接口(interface)落成多态
1.那里就不是后续了,是兑现接口的章程。
2.接口的艺术和虚幻一样没有方法体。
兑现:把上边完整的代码的父类改成接口
//接口
interface Person
{
void skill();
}
接下来把原先子类的 override 去掉
,因为接口(interface)是不可能被重写(override)的。虚方法(virtual),抽象(abstract)才能被重写
OK,接口完成多态也是成就了。
->virtual和override
virtual是为着让子类重写,所以virtual用在父类里;override代表重写父类方法,所以用在子类中。在父类的不二法门中加virtual表示
那些主意是虚方法,表示:假如在子类中写了一个均等的方法,在动用时就会调用子类中的方法,而不会调用父类中的那么些格局,就是说当子类中尚无那么些方法时,而又要用那么些法子,就会从父类中调用。而override写在子类中时就印证在子类中重写了父类的法门;要是父类中没有写virtual子父类中又写override就会时有暴发万分,2个一律的章程就会争持,子类中的方法就不可能重写。假若父类的艺术中写了virtual而子类的艺术中尚无写override,这种景观是足以生出的,子类一样重写的父类的方式。而要是在子类中应用new关键字的话也是能重写父类方法的。
测算不相同岗位职工的薪水
# 公司内三种员工
# 部门经理 - 固定月薪15000元 程序员 - 150元/小时 销售员 - 1200 + 5%销售额
# 给员工信息,算出员工月薪
from abc import ABCMeta,abstractmethod
# 强制子类必须实现方法
class Employee(object, metaclass=ABCMeta):
"""员工"""
def __init__(self, name):
"""
初始化方法
:param name: 姓名
"""
self._name = name
@property
def name(self):
return self._name
# 抽象方法
@abstractmethod
def get_salary(self):
"""
计算月薪
:return: 月薪
"""
pass
class Manger(Employee):
"""部门经理"""
def get_salary(self):
return 15000
class Programmer(Employee):
def __init__(self, name):
super().__init__(name)
# 联系不是最紧密的属性
# 更适合赋默认值
# 用setter方法进行修改
self._working_hour = 0
@property
def working_hour(self):
return self._working_hour
@working_hour.setter
def working_hour(self, working_hour):
self._working_hour = working_hour \
if working_hour > 0 else 0
def get_salary(self):
return 150 * self._working_hour
class Salesman(Employee):
def __init__(self, name):
# super(Salesman, self) 若Salesman只继承了一个父类,括号内的内容可以省略
super(Salesman, self).__init__(name)
self._sales = 0
@property
def sales(self):
return self._sales
@sales.setter
def sales(self, sales):
self._sales = sales if sales > 0 else 0
def get_salary(self):
return 1200 + self._sales * 0.05
def main():
emps = [
Manger('刘备'), Programmer('zhu'),
Manger('cao'), Salesman('gou'),
Salesman('lv'), Programmer('zhang')
]
for emp in emps:
# isinstance识别对象的类型
if isinstance(emp, Programmer):
emp.working_hour= int(input('输入%s本月工作时间:' % emp.name))
elif isinstance(emp, Salesman):
emp.sales = int(input('输入%s本月销售额' % emp.name))
# 同样是接收get_salary这个消息,但是不同的员工表现出了不同的行为
# 因为三个子类都重写了get_salary方法,所以这个方法会表现出多态行为
print('%s本月工资为:¥%.2f元' % (emp.name, emp.get_salary()))
if __name__ == '__main__':
main()
主意的多态行为
要是一个父类同时被多少个子类继承,而多个子类都重写了父类中的同一个办法,那么那个措施予以表现出了多态行为。上边的实例中的get_salary方法就显现出来多态行为。
->public 定义那个类无处可以被访问
->internal 本程序集访问 本项目
->private 只可以在本类中走访
->protected 只好在本类和子类中访问
->abstract表示抽象
2、抽象类:
他是用于指定蓝图的,是法规的制定者或规划者,是领导者,他协调不做,让手下去做,并且手下的力量不等,完结的效益也不一致。所以抽象类也可以兑现多态。
->抽象方法:指定蓝图用的,用于子类都必须有,但每个子类的方法已毕的功用都不比,用那一个在父类中限制子类必须有的艺术,并且子类完成了团结与我区其他方法体。
->例子:所有国家的人都会说话,但每个国家的人说的语言都不一样,所以把出口定义成抽象方法,定义在抽象类人中,在概念每个国家的人类时都不可以不有出口的艺术,并且每个国家都能说自己的语言。
3、接口
个别子类拥有的点子,定义一个成效(接口),哪个人想拥有这一个职能就延续(接口)。
->例子:接口就是一个正经,比如收作业这一个功能接口,既不可能定义在父类人类中,因为学生要收作业,老师要收作业,不过工程师不必要收作业;而定义在父类中得以用虚方法和架空方法,子类工程师不必要收作业这么些功用,就无法定义在父类中。所以要定义一个接口成效,那么子类何人想用这一个接口成效一旦继续接口就行了。
代码演示:
抽象类
namespace _03抽象
{
class Program
{
static void Main(string[] args)
{
while (true)
{
Person p = CreatePerson();
p.Say();
Console.ReadKey();
}
}
static Person CreatePerson()
{
//简单工厂模式
Random r = new Random();
int i = r.Next(1, 4);
switch (i)
{
case 1:
return new 中国人();
case 2:
return new 日本人();
default:
return new 韩国人();
}
}
}
abstract class Person
{
string name;
public string Name
{
get { return name; }
set { name = value; }
}
public abstract void Say();
}
class 中国人 : Person
{
public override void Say()
{
Console.WriteLine("中国话");
}
}
class 日本人 : Person
{
public override void Say()
{
Console.WriteLine("日语");
}
}
class 韩国人 : Person
{
public override void Say()
{
Console.WriteLine("韩语");
}
}
}
虚方法
namespace _04虚方法
{
class Program
{
static void Main(string[] args)
{
Person p;
p = new 成年人();
p.Go();
p = new 老年人();
p.Go();
p = new 脚残疾的人();
p.Go();
Console.ReadKey();
}
}
class Person
{
string name;
public string Name
{
get { return name; }
set { name = value; }
}
public virtual void Go()
{
Console.WriteLine("用脚走路!");
}
}
class 成年人 : Person
{
}
class 老年人 : Person
{
}
class 脚残疾的人 : Person
{
public override void Go()
{
Console.WriteLine("脚残,用手走~!");
}
}
}
接口
namespace _05接口
{
interface I收作业
{
void 都给我交作业();
}
class Program
{
static void Main(string[] args)
{
}
}
class Person
{
string name;
public string Name
{
get { return name; }
set { name = value; }
}
}
class 老师 : Person,I收作业
{
public void 都给我交作业()
{
Console.WriteLine("都交作业了!");
}
}
class 学生 : Person, I收作业
{
public void 都给我交作业()
{
Console.WriteLine("都交作业了!");
}
}
class 工程师 : Person
{
}
}