基础巩固,类和目的

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();
?>

输出:

说话走路小学生考试吃东西

先用2个skill类继承student类,然后再用pupil类继承skill类,那样就一定于pupil类继承了student类和skill类。

办法重写
若果要贯彻的三个类有三头个性,那么就足以将那个合伙的性状抽象出2个父类。
譬如说,有小学生类和中学生类,那样的七个类,他们都以学员,那么就足以抽象出壹个学童类,学生都会考查,那么就把试验那么些主意写在学员那一个类里面。
那么问题即便,小学生是小学生的考试,中学生是中学生的试验,作者不能都输出考试,那里就用到了主意重写。
在子类中定义1个与父类一样的不二法门,那样实践的时候,父类中的方法就会被覆盖,从而输出的唯有子类中定义的办法。
举例:

<?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.每2个目标都是无比的
3.目标可以归入某些类
4.目的是由类创设出来的,是实际的

多态 

只要要简明的讲述多态的话,作者个人是那般敞亮的:透过延续,父类定义方法,具休的落实由子类举办。

  ① 、类的一连(虚方法) ; 二 、抽象类;   叁 、接口   

定义类和创立对象

  • #### 定义类

定义类必要做两件事:数据抽象和行事抽象
数据抽象:抽取对象的一块儿的静态特征,称为属性;
行为抽象:抽取对象的同步的动态特征,称为方法。
如定义一个类为学习者,学生的质量包罗:姓名、年龄等,学生的作为包罗:上课、考试等。
定义类的格式: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();
        }
    }

输出:

亚洲必赢官网 1

 通过这几个例子 Person 类定义了skill方法,方法的现实落实由子类举办。

 

  ① 、类的继承

实例

用面向对象的盘算写程序的长河就是指给目的发1个音信,只要对象吸收到这几个消息,就会自行完毕这几个行为。要到位这几个顺序有贰个步骤:
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();
        }
    }

输出:

亚洲必赢官网 2

可以见到,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()

那么首先伸张2个厂子类

生存中工厂是用来加工的出品的,同样那里也是依照传入的参数,加工后归来对应的结果

方方面面代码

//父类
    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();
        }
    }

 

实践结果:

亚洲必赢官网 3

亚洲必赢官网 4

那时候,多态+简单工厂就早已落实了。

  ->关键字用在何地?    

抽象类

亚洲必赢官网,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就会发生越发,3个一律的法门就会冲突,子类中的方法就不可以重写。借使父类的措施中写了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()

方法的多态行为
即使三个父类同时被两个子类继承,而两个子类都重写了父类中的同2个方法,那么这么些点子予以表现出了多态行为。上面的实例中的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
    {

    }
}

 

网站地图xml地图