面向对象,承接与多态

作者:计算机知识

 

面向对象有包装、承继、多态那五特性状,面向对象编制程序根据现实世界的性状来治本复杂的东西,把它们抽象为目的,具备友好的情景和行事,通过对新闻的影响来成功任务。这种编制程序方法提供了特别有力的五种性,大大扩大了代码的选拔机会,扩展了先后支付的快慢,将富有独立性特制的程序代码包装起来,修改部分程序代码时不至于会潜移默化到程序的别的部分。

面向对象有包装、承接、多态那四个特点,面向对象编制程序遵照现实世界的特色来管理复杂的东西,把它们抽象为目的,具有温馨的景色和行为,通过对音信的反应来成功职责。这种编制程序方法提供了分外强劲的各种性,大大增添了代码的录用机会,扩展了先后开辟的速度,将具备独立性特制的程序代码包装起来,修改部分程序代码时不至于会潜移默化到程序的任何一些。

面向对象之继续和多态

此伏彼起 子类承接父类全体机能

class Animal(object):
    def run(self):
        print('animal is running...')
# 创建Animal实例
animal = Animal()
animal.run()

# Dog类
class Dog(Animal):
    pass

# 创建Dog 实例

dog = Dog()

# 调用Dog类继承来自于Animal类的run方法
dog.run() 

近期本身有這样一个要求 就是分歧子类承接父类调用run(),输出分裂的音讯,那么大家就供给在子类里边重新定义该格局来覆盖父类中的方法,這叫做多态

# Cat类 继承 Animal
class Cat(Animal):
    def run(self):
        print('cat is running...')

cat = Cat()
cat.run()

class Monkey(Animal):
    def run(self):
        print('Monkey is running...')
monkey = Monkey()
monkey.run()
# 现在输出了不同信息,但是每次都要写這么多,感觉多态也挺麻烦的,那我们再优化下:

print('-------------------------------------')
def _run(animal):
    animal.run()
    animal.run()

_run(Dog())
_run(Cat())
_run(Monkey())

# 這样就体现出多态的好处了 
# 我们也可以还派生出一些类来, 比如:
class Tortoise(Animal):
    def run(self):
        print('Tortoise is running slowly...')
_run(Tortoise())

静态语言Java和动态语言Python的界别:
对于静态语言(举例Java)来讲,假设急需传入Animal类型,则传出的指标必须是Animal类型或许它的子类,不然,将无法调用run()方法
对于Python那样的动态语言来讲,则不必然必要传入Animal类型。大家只须求有限扶助传入的指标有贰个run()方法就足以了:
那正是动态语言的“鸭子类型”,它并不要求严俊的接轨体系,叁个指标只要“看起来像鸭子,走起路来像鸭子”,那它就能够被作为是鸭子。 申明:

print('--------------------------------------')

class Rabbit(object):
    def run(self):
        print('Rabbit is running...')

_run(Rabbit()) # Rabbit is running...

代码裤子:

 

 

小结

继续可以把父类的具备作用都一向拿过来,那样就不要重零做起,子类只需要新扩展自身特有的点子,也能够把父类不切合的点子覆盖重写。

动态语言的野鸭类型特点决定了一而再不像静态语言那样是必须的。

保养入微一波!喜欢一波!本人是前端菜鸟,正在做自个儿的个人博客邓鹏的博客,迎接来沟通学习, 使用的技艺 vue koa贰 mysql php nginx!

在线编程:https://mybinder.org/v2/gh/lotapp/BaseCode/master
在线预览:http://github.lesschina.com/python/base/oop/2.持续与多态.html

1.封装

1.封装

2.继承 ¶

种种对象都带有它举办操作所急需的有着消息,封装只公开代码单元的对外接口,而隐蔽其切实贯彻,尽量不对外祖父开代码。使用封装有诸多便宜,从设计角度来讲,封装能够对外屏蔽部分重中之重的消息,比方选用微机的人若是通晓怎么选取微型Computer就足以,不用知道这几个效用具体是怎么落到实处的;从安全性思索,封装使对代码的退换尤其安全和轻易,封装鲜明的建议了如何属性和方法是表面能够访问的,那样当必要调治那些类的代码时,只要保险国有属性不变,公有方法的参数和再次回到值类型不改变,那么就足以痛快的修改这些类,而不会影响到程序的任何一些;封装还幸免了命名争持的主题材料,封装有隔离作用,分裂的类中得以有雷同名称的秘技和脾性,但不会搅乱,也足以削减耦合。

每种对象都饱含它进行操作所需求的富有新闻,封装只公开代码单元的对外接口,而隐藏其切实达成,尽量不对曾祖父开代码。使用封装有诸多功利,从希图角度来讲,封装能够对外屏蔽部分第3的音信,比如利用Computer的人如果知道怎么利用Computer就足以,不用知道那么些意义具体是怎么落实的;从安全性挂念,封装使对代码的更动尤其安全和轻易,封装明显的建议了怎么属性和章程是外部能够访问的,那样当必要调解那些类的代码时,只要保障国有属性不变,公有方法的参数和再次来到值类型不改变,那么就足以痛快的修改这一个类,而不会影响到程序的其余一些;封装还制止了命名争辨的难点,封装有隔开分离效率,分裂的类中得以有雷同名称的主意和品质,但不会搅乱,也得以减小耦合。

2.1.单继承 ¶

在OOP中,当我们定义贰个Class的时候,能够从某些现存的Class承接

新的Class称为子类,而被一而再的class称为 基类 或然 父类

Python的几次三番格式 ==> xxx(base_class)

小明神采飞扬的听着导师开新课,不一会就映注重帘了八个演示德姆o:

In [1]:

class Animal(object):
    def eat(self):
        print("动物会吃")

class Cat(Animal):
    # 注意一下Python的继承格式
    pass

class Dog(Animal):
    pass

def main():
    cat = Cat()
    dog = Dog()
    cat.eat()
    dog.eat()

if __name__ == "__main__":
    main()

面向对象,承接与多态。 

动物会吃
动物会吃

 

当听见导师说:“ 私有的习性方法 不会被子类承接 ”的时候,小明心里1颤,联想到事先讲的 类属性实例属性实例方法类方法静态方法,于是赶紧写个德姆o验证一下:

In [2]:

class Animal(object):
    # 类属性
    name = '动物'

    def __init__(self):
        # 实例属性
        self.age = 1

    def __bug(self):
        """实例私有方法"""
        print("我是动物类身上的私有方法:bug")

    def eat(self):
        """实例方法"""
        print("我是实例方法,动物会吃哦~")

    @classmethod
    def call(cls):
        """类方法"""
        print("我是类方法,动物会叫哦")

    @staticmethod
    def play():
        """静态方法"""
        print("我是静态方法,动物会玩耍哦")


class Dog(Animal):
    pass


def main():
    dog = Dog()
    # 实例属性
    print(dog.age)
    # 实例方法
    dog.eat()

    # 类属性
    print(dog.name)
    # 类方法
    dog.call()
    Dog.call()
    Animal.call()

    # 静态方法
    dog.play()
    Dog.play()
    Animal.play()


if __name__ == '__main__':
    main()

 

1
我是实例方法,动物会吃哦~
动物
我是类方法,动物会叫哦
我是类方法,动物会叫哦
我是类方法,动物会叫哦
我是静态方法,动物会玩耍哦
我是静态方法,动物会玩耍哦
我是静态方法,动物会玩耍哦

 

来张图就懂了,不是 私有的 都能访问:

图片 1

这时候,小明老载歌载舞了,单回头一想 ==> 不正确啊,dog应该有其对应的办法呢,C#有 虚方法重写,Python怎么搞?在 子类里面又 怎么调用父类方法呢?

对此小明的唤起老师很欢畅,于是点名小潘来写叁个子类调用父类的demo(老师前几天从窗户里看见小潘有预习):

In [3]:

# 调用父类的方法
class Father(object):
    def eat(self):
        print("文雅的吃饭")


class Son(Father):
    def eat(self):
        # 调用父类方法第1种(super().方法)
        super().eat()


class GrandSon(Son):
    def eat(self):
        # 调用父类方法第2种(记得传self)
        Son.eat(self)


def main():
    xiaoming = Son()
    xiaoming.eat()

    xiaoli = GrandSon()
    xiaoli.eat()


if __name__ == '__main__':
    main()

 

文雅的吃饭
文雅的吃饭

 

貌似我们应用 super().方法来调用父类方法

其次种办法 类名.方法(self)千万别忘记传self哦

对了,C#是用base关键词,别搞混了

小明那时候可不开心了,风头怎么能被小潘全部抢劫呢,赶紧问问旁边同样预习的伟哥

不一会儿淡定的发了份重写父类方法的demo给老师:

In [4]:

# 重写父类方法==>子类和父类有同名方法
class Father(object):
    def __init__(self, name):
        self.name = name

    def eat(self):
        print("%s喜欢文雅的吃饭" % self.name)


class Son(Father):
    def __init__(self, name):
        super().__init__(name)

    def eat(self):
        print("%s喜欢大口吃饭大口喝酒" % self.name)


def main():
    xiaoming = Father("小明")
    xiaoming.eat()

    xiaopan = Son("小潘")
    xiaopan.eat()


if __name__ == "__main__":
    main()

 

小明喜欢文雅的吃饭
小潘喜欢大口吃饭大口喝酒

 

教员半喜半忧的说道:“小明同学啊,你也年轻了,怎么跟孩子同1啊?案例不错,但是怎么能人身攻击人家小潘了?”

当子类和父类都留存同样的 eat()方法时,我们说,子类的 eat()蒙面了父类的 eat()

在代码运转的时候,总是会调用子类的 eat() 那样,大家就获得了三番五次的另1个好处: 多态

 

 

2.2.多继承 ¶

在讲 多态事先,大家先引入一下Python的 多继承 对,你未曾听错

Java、C#都是单承接,多完结。Python和C 同样,能够多再三再四,先不用嘲笑, 正规使用其实很便利的

来个案例看看:

In [5]:

# 多继承引入
class Father(object):
    def eat(self):
        print("文雅的吃饭")


class Mom(object):
    def run(self):
        print("小碎步")


class Son(Father, Mom):
    pass


def main():
    son = Son()
    son.eat()
    son.run()


if __name__ == '__main__':
    main()

 

文雅的吃饭
小碎步

 

持续能够把父类的保有机能都平素拿过来,那样就无需重0开端写代码,子类只需求新扩充本归西意的措施,也得以把父类不合乎的艺术覆盖重写

小心三个地方,假如父类里面有同名方法咋做了?到底调哪个吧?

使用 子类名.__mro__可以看在调方法的时候寻找顺序

貌似同名方法都是 先看本人有未有,然后看后续顺序,譬喻那边 先看Mom再看Father

In [6]:

# 如果父类里面有同名方法怎么知道调哪个?
class Father(object):
    def eat(self):
        print("文雅的吃饭")


class Mom(object):
    def eat(self):
        print("开心的吃饭")


class Son(Mom, Father):
    pass


def main():
    son = Son()
    son.eat()
    print(Son.__mro__)  # 一般同名方法都是先看自己有没有,然后看继承顺序,比如这边先看Mom再看Father


if __name__ == '__main__':
    main()

 

开心的吃饭
(<class '__main__.Son'>, <class '__main__.Mom'>, <class '__main__.Father'>, <class 'object'>)

 

Python的多承继最佳是当C#抑或Java里面包车型大巴接口使用,那样结构不会混杂( 出奇情形除了)

来个例子:

class Animal(object):
    pass

class Flyable(object):
    """飞的方法"""
    pass

class Runable(object):
    """跑的方法"""
    pass

class Dog(Animal, Runable):
    pass

class Cat(Animal, Runable):
    pass

class Bird(Animal, Flyable):
    pass

class Dack(Animal, Runable, Flyable):
    """鸭子会飞也会跑"""
    pass

和C#一样,Python的 父类构造函数不会被一连

实际从能源角度也不应有被延续,要是有一w个子类,那每一个子类里面都有一个父类方法,想想那是何等浪费的壹件业务?


2.继承

2.继承

2.3.C#继承 ¶

下课后,小明认真怀想计算,然后相比较Python写下了C#版的延续:

概念1个生人

public class Person
{
    public string Name { get; set; }
    public ushort Age { get; set; }

    public Person(string name, ushort age)
    {
        this.Name = name;
        this.Age = age;
    }
    public void Hi()//People
    {
        Console.WriteLine("Name: "   this.Name   " Age: "   this.Age);
    }
    public virtual void Show()//People
    {
        Console.WriteLine("Name: "   this.Name   " Age: "   this.Age);
    }
}

概念三个学员类

public class Student : Person
{
    #region 属性
    /// <summary>
    /// 学校
    /// </summary>
    public string School { get; set; }
    /// <summary>
    /// 班级
    /// </summary>
    public string StrClass { get; set; }
    /// <summary>
    /// 学号
    /// </summary>
    public string StrNum { get; set; }
    #endregion

    #region 构造函数
    /// <summary>
    /// 调用父类构造函数
    /// </summary>
    /// <param name="name"></param>
    /// <param name="age"></param>
    public Student(string name, ushort age) : base(name, age)
    {

    }
    public Student(string name, ushort age, string school, string strClass, string strNum) : this(name, age)
    {
        this.School = school;
        this.StrClass = strClass;
        this.StrNum = strNum;
    } 
    #endregion

    /// <summary>
    /// new-隐藏
    /// </summary>
    public new void Hi()//Student
    {
        Console.WriteLine("Name: "   this.Name   " Age: "   this.Age   " School: "   this.School   " strClass: "   this.StrClass   " strNum: "   this.StrNum);
    }
    /// <summary>
    /// override-覆盖
    /// </summary>
    public override void Show()//Student
    {
        Console.WriteLine("Name: "   this.Name   " Age: "   this.Age   " School: "   this.School   " strClass: "   this.StrClass   " strNum: "   this.StrNum);
    }
}

调用一下:

Person p = new Student("app", 10, "北京大学", "001", "01001");
p.Hi(); p.Show();

Console.WriteLine();

Student s = p as Student;
s.Hi(); s.Show();

结果:

Name: app Age: 10
Name: app Age: 10 School: 北京大学 strClass: 001 strNum: 01001
Name: app Age: 10 School: 北京大学 strClass: 001 strNum: 01001
Name: app Age: 10 School: 北京大学 strClass: 001 strNum: 01001

承继能够采纳现成类的有所功效,并在毫无重新编辑原来的类的情事下,对这几个作用进行扩大。使用持续而发生的类被称为派生类或子类,而被持续的类则称为基类或超类或父类。承袭表示3个连串派生于一个基类型,它具备该基类型的保有成员字段和函数,其子类是对父类的庞大;接口承继是意味着1个类型只持续了函数的签名,未有承袭任何达成代码。承袭划分了类的档案的次序性,也足以说后续是对类的分组,父类代表的是抽象的类,更常用的类,而子类代表的是愈来愈现实,更为细化的类;承袭是达成代码重用、扩张的要紧手腕。所谓抽象的类是指与现实的事项相挂钩,但只是公布全部而不是切实概念的类,例如说形状包涵星型、长方形、圆等,那时候形状是1个虚幻的定义,相当于1个父类,而正方形、圆柱形、圆是具体的造型,也正是是子类。

此起彼落能够运用现成类的享有功用,并在毫无重新编排原来的类的景况下,对这个作用举办扩大。使用持续而爆发的类被誉为派生类或子类,而被持续的类则称为基类或超类或父类。承继表示二个系列派生于2个基类型,它具有该基类型的有着成员字段和函数,其子类是对父类的恢弘;接口承袭是象征3个类型只持续了函数的签署,未有继续任何完成代码。承接划分了类的档期的顺序性,也得以说后续是对类的分组,父类代表的是抽象的类,更常用的类,而子类代表的是更进一步实际,更为细化的类;承袭是贯彻代码重用、扩张的首要花招。所谓抽象的类是指与具体的事项相挂钩,但只是表述全部而不是实际概念的类,比方说形状包罗圆柱形、纺锤形、圆等,那时候形状是二个虚无的概念,也就是1个父类,而星型、星型、圆是具体的形象,相当于是子类。

2.4C#接口的多完结 ¶

概念七个接口:

public interface IRun
{
    //什么都不用加
    void Run();
}

public interface IEat
{
    void Eat();
}

概念四个Dog类来落到实处五个接口,那样dog就有了run和eat的方法了

var dog = new Dog();
dog.Eat();
dog.Run();

结果:

狗狗吃
狗狗跑

 

 

本文由bwin必赢发布,转载请注明来源

关键词: 随笔 .NET技术 WinForm