zoukankan      html  css  js  c++  java
  • 面向对象三大特性——继承高阶(接口和抽象类)

    一、接口(Interface)

      在C++、JAVA等程序开发时,往往会利用到接口。接口其实就是:自己提供给使用者来调用自己功能的方式方法入口。

    =================第一部分:Java 语言中的接口很好的展现了接口的含义: IAnimal.java
    /*
    * Java的Interface接口的特征:
    * 1)是一组功能的集合,而不是一个功能
    * 2)接口的功能用于交互,所有的功能都是public,即别的对象可操作
    * 3)接口只定义函数,但不涉及函数实现
    * 4)这些功能是相关的,都是动物相关的功能,但光合作用就不适宜放到IAnimal里面了 */
    
    package com.oo.demo;
    public interface IAnimal {
        public void eat();
        public void run(); 
        public void sleep(); 
        public void speak();
    }
    
    =================第二部分:Pig.java:猪”的类设计,实现了IAnnimal接口 
    package com.oo.demo;
    public class Pig implements IAnimal{ //如下每个函数都需要详细实现
        public void eat(){
            System.out.println("Pig like to eat grass");
        }
    
        public void run(){
            System.out.println("Pig run: front legs, back legs");
        }
    
        public void sleep(){
            System.out.println("Pig sleep 16 hours every day");
        }
    
        public void speak(){
            System.out.println("Pig can not speak"); }
    }
    
    =================第三部分:Person2.java
    /*
    *实现了IAnimal的“人”,有几点说明一下: 
    * 1)同样都实现了IAnimal的接口,但“人”和“猪”的实现不一样,为了避免太多代码导致影响阅读,这里的代码简化成一行,但输出的内容不一样,实际项目中同一接口的同一功能点,不同的类实现完全不一样
    * 2)这里同样是“人”这个类,但和前面介绍类时给的类“Person”完全不一样,这是因为同样的逻辑概念,在不同的应用场景下,具备的属性和功能是完全不一样的 */
    
    package com.oo.demo;
    public class Person2 implements IAnimal { 
        public void eat(){
            System.out.println("Person like to eat meat");
        }
    
        public void run(){
            System.out.println("Person run: left leg, right leg");
        }
    
        public void sleep(){
            System.out.println("Person sleep 8 hours every dat"); 
        }
    
        public void speak(){
            System.out.println("Hellow world, I am a person");
        } 
    }
    
    =================第四部分:Tester03.java
    package com.oo.demo;
    
    public class Tester03 {
        public static void main(String[] args) {
            System.out.println("===This is a person==="); 
            IAnimal person = new Person2();
            person.eat();
            person.run();
            person.sleep();
            person.speak();
    
            System.out.println("
    ===This is a pig===");
            IAnimal pig = new Pig();
            pig.eat();
            pig.run();
            pig.sleep();
            pig.speak();
        } 
    }
    
     java中的interface
    java中interface

    1、使用接口的好处

      接口提取了一群类共同的函数,可以把接口当做一个函数的集合。然后让子类去实现接口中的函数。这样做得好处也就是实现了归一化。

    二、归一化

      归一化:只要是基于同一个接口实现的类,那么这些类产生的对象在使用时,从用法来说是一样的。

    1、归一化的好处

      1)让使用者无需关心对象的类,只需要知道这些对象都具备某些功能即可,降低使用难度。

      2)让高层的外部使用者可以不加区分地处理所有接口兼容的对象集合。

    1、就好象linux的泛文件概念一样,所有东西都可以当文件处理,不必关心它是内存、磁盘、网络还是屏幕(当然,对底层设计者,当然也可以区分出“字符设备”和“块设备”,然后做出针对性的设计:细致到什么程度,视需求而定)。
    
    2、再比如:我们有一个汽车接口,里面定义了汽车所有的功能,然后由本田汽车的类,奥迪汽车的类,大众汽车的类,他们都实现了汽车接口,这样就好办了,大家只需要学会了怎么开汽车,那么无论是本田,还是奥迪,还是大众我们都会开了,开的时候根本无需关心我开的是哪一类车,操作手法(函数调用)都一样
    接口兼容处理例子

    三、python中实现接口

      在python中并没有interface关键字,如果想去模仿接口概念,有两种方法:

    方法一:借助第三方模块 http://pypi.python.org/pypi/zope.interface

    方法二:使用继承。

    1、继承的两种用途

      1)继承基类的方法,并做出自己的改变或扩展(代码重用)。

      实际这种用法意义不大,甚至往往是有害的,因为它会使得子类和基类出现强耦合

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

    # 正常实现调用
    class Applepay:
        def pay(self,money):
            print('apple pay 支付了%s' %money)
    
    class Alipay:
        def pay(self,money):
            print('支付宝  支付了%s' %money)
    
    def payment(pay_obj,money):  #实例化的另一种调用,这个方法让实例化的时候按照payment调用:就像下面的payment(apple1,200)
            pay_obj.pay(money)
    
    apple1 = Applepay()
    # apple1.pay(200)
    payment(apple1,200)
    """
    apple pay 支付了200
    """
    正常实现调用
    # 2.有时候写的时候会把方法写错,自己定义一个主动报错
    # 接口初成:手动报异常:NotImplementedError来解决开发中遇到的问题
    class Payment:
        def pay(self):
            raise NotImplementedError  #主动让程序报错
    
    class Wechatpay(Payment): #微信支付
        def pay(self,money):
            print('微信支付了%s元',money)
    
    class QQchatpay(Payment): #QQ支付
        def fuqian(self,money):
            print('QQ支付了%s元',money)
    
    p = Wechatpay()
    p.pay(200)   #不报错  # 微信支付了%s元 200
    q = QQchatpay()  
    q.pay()  #报错
    主动报错
    # 3.借用abc模块来实现接口
    #接口类(就是为了提供标准,约束后面的子类)
    from abc import ABCMeta,abstractmethod
    class Payment(metaclass=ABCMeta):
        @abstractmethod
        def pay(self,money):
            pass
    
    class Wechatpay(Payment):
        def fuqian(self,money):
            '''实现了pay的功能,但是方法名字不一样'''
            print('微信支付了%s元'%money)
    
    class Alipay:
        def pay(self,money):
            print('支付宝  支付了%s' %money)
    
    # p = Wechatpay() #报错了(因为上面定义了一个接口类,接口类里面
    # 定义了一个pay方法,而在下面的Wechatpay方法里没有pay方法,不能
    # 调用,在接口类里面约束一下,接口类里的pay方法里面不能写其他,直接pass)
    a = Alipay()
    a.pay(200)
    """
    支付宝  支付了200
    """
    # p = Payment() #接口类不能被实例化
    abc模块实现接口

      由上面的例子可以归结,接口也就是做约束,让下面的类的方法都按照接口类中给出的方法去定义。如果接口类里有的方法类里面没有,则这个类不能被实例化。而abc模块的使用,则说明了接口和抽象类的关联性。

    四、抽象类

    1、抽象类概念

      抽象类往往用来表征对问题领域进行分析、设计中得出的抽象概念,是对一系列看上去不同,但是本质上相同的具体概念的抽象。在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。

    2、抽象类特点

      抽象类与普通类的特殊之处就是只能被继承抽象类是不完整的,它只能用作基类),不能被实例化

    3、抽象类用处

      在面向对象方法中,抽象类主要用来进行类型隐藏和充当全局变量的角色。降低使用者的使用复杂度,统一标准。

    4、抽象类的实现

      python的abc模块中定义了抽象类的metaclass类ABCMeta,以及抽象方法装饰器abstractmethod, abstractclassmethod, abstractstaticmethod,抽象property装饰器abstractproperty等。可以基于这些工具来实现自己的抽象类。

    import abc    #利用abc模块实现抽象类
    
    class Animal(metaclass=abc.ABCMeta):  # 类似接口,只定义规范,不实现具体的代码
        @abc.abstractclassmethod
        def run(self):
            pass
    
        @abc.abstractclassmethod
        def eat(self):
            pass
    
    # 尝试实例化抽象类:结果失败
    # animal = Animal()
    # TypeError: Can't instantiate abstract class Animal with abstract methods eat, run
    
    class People(Animal):
        def run(self):  # 不符合规范,不允许实例化
            print('people is walking')
    
        def eat(self):
            print('people is eating')
    
    class Pig(Animal):
        def run(self):
            print('Pig is running')
    
        def eat(self):
            print('Pig is eating')
    
    class Dog(Animal):
        def run(self):
            print('Dog is zouing')
    
        def eat(self):
            print('Dog is eating')
    
    peo1 = People()
    pig1 = Pig()
    Dog1 = Dog()
    
    peo1.eat()
    pig1.eat()
    Dog1.run()
    """
    people is eating
    Pig is eating
    Dog is zouing
    """
    抽象类实现
    #一切皆文件
    import abc #利用abc模块实现抽象类
    
    class All_file(metaclass=abc.ABCMeta):
        all_type='file'
        @abc.abstractmethod #定义抽象方法,无需实现功能
        def read(self):
            '子类必须定义读功能'
            pass
    
        @abc.abstractmethod #定义抽象方法,无需实现功能
        def write(self):
            '子类必须定义写功能'
            pass
    
    # class Txt(All_file):
    #     pass
    #
    # t1=Txt() #报错,子类没有定义抽象方法
    
    class Txt(All_file): #子类继承抽象类,但是必须定义read和write方法
        def read(self):
            print('文本数据的读取方法')
    
        def write(self):
            print('文本数据的读取方法')
    
    class Sata(All_file): #子类继承抽象类,但是必须定义read和write方法
        def read(self):
            print('硬盘数据的读取方法')
    
        def write(self):
            print('硬盘数据的读取方法')
    
    class Process(All_file): #子类继承抽象类,但是必须定义read和write方法
        def read(self):
            print('进程数据的读取方法')
    
        def write(self):
            print('进程数据的读取方法')
    
    wenbenwenjian=Txt()
    
    yingpanwenjian=Sata()
    
    jinchengwenjian=Process()
    
    #这样大家都是被归一化了,也就是一切皆文件的思想
    wenbenwenjian.read()
    yingpanwenjian.write()
    jinchengwenjian.read()
    
    print(wenbenwenjian.all_type)
    print(yingpanwenjian.all_type)
    print(jinchengwenjian.all_type)
    一切皆文件

    五、抽象类与接口

      抽象类表示该类中可能已经有一些方法的具体定义,但是接口就仅仅只能定义各个方法的界面(方法名,参数列表,返回类型),并不关心具体细节。 

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

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

    1、抽象类和接口相同点

      1、不能实例化;

      2、包含未实现的方法声明;

      3、派生类必须实现未实现的方法,抽象类是抽象方法,接口则是所有成员(不仅是方法包括其他成员)

    2、不同点

      1、类可以实现无限个接口,但仅能从一个抽象(或任何其他类型)类继承,从抽象类派生的类仍可实现接口,从而得出接口是用来解决多重继承问题的。

      2、抽象类当中可以存在非抽象的方法,可接口不能。

      3、抽象类中的成员变量可以被不同的修饰符来修饰,可接口中的成员变量默认的都是静态常量(static final)。

      4、抽象类是对象的抽象,然而接口是一种行为规范。

  • 相关阅读:
    阿里p3c(代码规范,eclipse插件、模版,idea插件)
    mac 电脑 打开隐藏文件
    groovy安装 ideal
    JNI字段描述符
    java 中函数的参数传递详细介绍
    java把函数作为参数传递
    Android获取wifi MAC,关闭的wifi不能获取
    Android权限操作之uses-permission详解
    Android Studio断点调试
    android 启动socket 失败:socket(af_inet sock_stream 0) 返回-1
  • 原文地址:https://www.cnblogs.com/xiugeng/p/8926780.html
Copyright © 2011-2022 走看看