、接口与类的区别;

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了、接口与类的区别;相关的知识,希望对你有一定的参考价值。

、接口与类的区别;

接口并不是类,编写接口的方式和类很相似,但是它们属于不同的概念。类描述对象的属性和方法。接口则包含类要实现的方法。
除非实现接口的类是抽象类,否则该类要定义接口中的所有方法。
接口无法被实例化,但是可以被实现。一个实现接口的类,必须实现接口内所描述的所有方法,否则就必须声明为抽象类。另外,在 Java 中,接口类型可用来声明一个变量,他们可以成为一个空指针,或是被绑定在一个以此接口实现的对象。

接口与类的区别:
接口不能用于实例化对象。
接口没有构造方法。
接口中所有的方法必须是抽象方法。
接口不能包含成员变量,除了 static 和 final 变量。
接口不是被类继承了,而是要被类实现。
接口支持多继承。
参考技术A 首先讲“类”:
在面对对象编程中,类代表着对象的类别。利用建模抽象来定义那些表露该抽象的对象的性质和行为。在这里,类的属性对应着对象的性质,在Java中由字段来表示,类的方法对应对象的行为,在Java中也是用方法来表示。类为对象提供了契约和实现。二者的区别在于契约定义了提供哪些服务,而实现定义了如何提供服务。
比如轿车有很多品牌,但它们都是轿车,所以我把很多的不同品牌的轿车抽象为轿车这一类,不去管它是哪个品牌的。
既然类是一些具有公共性质和行这的事物的抽象或者说归类,那么就一定可以通过类反过来对它抽象的对象进行实例化。
比如我有一辆本田轿车,所以我可以把综从轿车这个类中实例化出来,告诉大家这是一辆本田轿车,而不是其他品牌的车。
现在讲“接口”:
当类所代表的抽象是如此的一般化,以至于需要特殊化后才有实际意义时可以将它定义为一个接口
还是以车为例,比如我就想抽象车这个事物,但是把它实例化还是没什么意义,因为不知道它到底是轿车还是火车还货车,我们只知道它属于车这一类。
接口和类的区别在于:
1.接口是不可实例化的,它类似于类中的抽象类。
2.接口只是规定了一组方法原型,没有任何实质性的语句。
3.类继承是单态的,而接口实现是多重的。
4.类继承时可以选择性的重载,覆盖父类的一些方法,而接口要求重写接口的全部方法。即使你不用也得实现。否则会编译时会报错
参考技术B 接口是声明类的标准行为,而类负责实现这些行为。 参考技术C 1、接口类似于类,但接口的成员都没有执行方式,它只是方法、属性、事件和索引的组合而已,并且也只能包含这四种成员;类除了这四种成员之外还可以有别的成员(如字段)。
2、不能实例化一个接口,接口只包括成员的签名;而类可以实例化(abstract类除外)。
3、接口没有构造函数,类有构造函数。
4、接口不能进行运算符的重载,类可以进行运算符重载。
5、接口的成员没有任何修饰符,其成员总是公共的,而类的成员则可以有修饰符(如:虚拟或者静态)。
6、派生于接口的类必须实现接口中所有成员的执行方式,而从类派生则不然。本回答被提问者和网友采纳

python 面向对象专题:元类type反射函数与类的区别特殊的双下方法

 

1. 元类type

  • type:获取对象从属的类

    Python中一切皆对象,类在某种意义上也是一个对象

    Python中自己定义的类,以及大部分内置类,都是由type元类(构建类)实例化得来的

    # type 获取对象从属于的类
    print(type(A))
    print(type(str))
    print(type(dict))
  • type与object的关系:

    object类是type类的一个实例 print(type(object))
    object类是type类的父类 print(issubclass(type,object))

2. 反射

  • 定义:通过字符串操作对象的方式,程序对自己内部代码的一种自省方式

  • 内置函数:hasattr getattr setattr delattr (attr 是属性的意思)

  • 反射可以作用的对象:实例对象,类,本模块,其他模块

    从对象角度应用反射

    class A:
        country = \'中国\'
        def __init__(self,name,age):
            self.name = name
            self.age = age
        def func(self):
            print(\'in A func\')
    obj = A(\'张三\',66)
    
    # hasattr: 判断有无属性
    print(hasattr(obj,\'name\'))
    print(hasattr(obj,\'country\'))   # 报错
    print(hasattr(obj,\'func\'))   # 报错
    
    # getattr: 获取属性
    if hasattr(obj,\'name\'):
        getattr(obj,\'name\')
        
    # setattr: 设置属性/delattr: 删除属性
    setattr(obj,\'sex\',\'\')
    delattr(obj,\'name\')

     

    从类的角度应用反射

    class A:
        country = \'中国\'
        def __init__(self,name,age):
            self.name = name
            self.age = age
        def func(self):
            print(self)
            print(\'in A func\')
    
    if hasattr(A,\'func\'):
        obj = A(\'张三\', 26)
        getattr(obj,\'func\')()
        getattr(A,\'func\')(obj)

     

    从其他模块应用反射

    import tbjx
    
    # 1. 找到tbjx对象的C类,实例化一个对象.
    obj = getattr(tbjx,\'C\')(\'123\')
    
    # 2. 找到tbjx对象的C类,通过对C类这个对象使用反射取到area.
    print(getattr(tbjx.C,\'area\'))
    
    # 3. 找到tbjx对象的C类,实例化一个对象,对对象进行反射取值.
    obj = getattr(tbjx,\'C\')(\'张三\')
    print(obj.name)
    print(getattr(obj,\'name\'))

     

    从当前模块应用反射

    def func1():
        print(\'in func1\')
    
    def func2():
        print(\'in func2\')
    
    def func3():
        print(\'in func3\')
    
    def func4():
        print(\'in func4\')
    
    
    import sys
    print(sys.modules[__name__])
    getattr(sys.modules[__name__],\'func1\')()
    getattr(sys.modules[__name__],\'func2\')()
    getattr(sys.modules[__name__],\'func3\')()
    
    # 本模块的模块名:sys.modules[__name__]

     

  • 反射应用示例:

    class User:
        def login(self):
            print(\'欢迎来到登录页面\')
    
        def register(self):
            print(\'欢迎来到注册页面\')
    
        def save(self):
            print(\'欢迎来到存储页面\')
    
    choose_dic = {
        1: User.login,
        2: User.register,
        3: User.save,
    }
    
    while 1:
        choose = input(\'请输入序号: \\n1: 登录\\n2: 注册\\n3: 存储\').strip()
        obj = User()
        choose_dic[int(choose)](obj)

     

3. 函数与类的区别

  • 函数都是显性传参,方法都是隐形传参

    class A:
        @classmethod
        def func(cls,a):
            pass
        @staticmethod
        def func1():
            pass
    
    A.func(666)
    A.func()

     

  • 通过打印函数名的方式,区别什么是方法,什么是函数

    def func1():
        pass
    class A:
        def func(self):
            pass
    print(func1)
    print(A.func)
    obj = A()
    print(obj.func)
    
    # 结果:
    <function func1 at 0x000000A9C59C1EA0>
    <function A.func at 0x000000A9C75DE268>
    <bound method A.func of <__main__.A object at 0x000000A9C744D4A8>>

     

  • 可以借助模块判断类中的是方法还是函数

           

from types import FunctionType
from types import MethodType
def func():
    pass
class A:
    def func(self):
        pass
obj = A()
print(isinstance(func,FunctionType))  # True
print(isinstance(A.func,FunctionType))  # True
print(isinstance(obj.func,FunctionType))  # False
print(isinstance(obj.func,MethodType))  # True

 

4. 特殊的双下方法

  • 特殊的双下方法: 原本是开发python这个语言的程序员用的.源码中使用的,双下方法: 你不知道你干了什么就触发某个双下方法

    # 1.__len__   len(b)执行b类从属父类的__len__方法,必须要有return int(返回值)
    class B:
        def __init__(self,name,age):
            self.name = name
            self.age =age
        def __len__(self):
            return len(self.__dict__)  # 2
    b = B(\'张三\',28)
    print(len(b))
    
    
    # 2.__hash__  hash()触发__hash__双下方法
    class A(object):
        def __hash__(self):
            return 123456
    obj = A()
    print(hash(obj))
    
    
    # 3.__str__ 里边必须有return "字符串"类型  (优先级高于__repr__)
    #   -  打印对象的时候,会触发__str__方法
    #   -  str转化也可以触发
    class A:
        def __init__(self,name,age):
            self.name = name
            self.age =age
        def __str__(self):
            print(\'触发str方法\')
            return f\'姓名: {self.name} 年龄: {self.age}\'
    a = A(\'张三\',35)
    
    # 打印对象触发__str__方法
    print(f\'{a.name}  {a.age}\')
    print(a)
    
    # 直接str转化也可以触发.
    print(str(a))
    
    
    
    # 4.__repr__  里边必须有return "字符串"类型
    #   -  打印对象的时候,会触发__repr__方法
    class A:
        def __init__(self,name,age):
            self.name = name
            self.age =age
        def __repr__(self):
            print(666)
            return f\'姓名: {self.name} 年龄: {self.age}\'
    
    a = A(\'张三\',35)
    print(a)
    print(repr(a))
    
    
    # 5.__call__  对象()触发对象从属类(父类)的__call__方法
    class Foo:
        def __init__(self):
            pass
        def __call__(self, *args, **kwargs):
            print(\'__call__\')
    obj = Foo()
    obj()
    
    
    # 6.__eq__   两对象==时触发,return True/false(可以返回数字,字符串 一般返回布尔值)
    class A(object):
        def __init__(self):
            self.a = 1
            self.b = 2
    
        def __eq__(self,obj):
            print(\'__eq__\')
            return True
    x = A()
    y = A()
    print(x == y)
    
    
    # 7.__del__ 析构方法 回收对象时触发__del__方法
    class A:
        def __del__(self):
            print(\'__del__\')
    obj = A()
    del obj
    
    
    # 8.__new__  new一个对象(构造方法),实例化对象的时候会触发,对象是object类的__new__方法,产生了一个对象
    class A(object):
        def __init__(self):
            print(\'in init function\')
    
        def __new__(cls, *args, **kwargs):
            print(\'in new function\')
            return object.__new__(A)
    
    # 对象是object类的__new__方法 产生了一个对象.
    a = A()
    
    # 类名()
    # 1. 先触发 object的__new__方法,此方法在内存中开辟一个对象空间.
    # 2. 执行__init__方法,给对象封装属性.
    
    # def __init__(self):(不能写返回值,因为__new__已经有返回值了,不能同时接收两个返回值,只能接收__new__的返回值)
        
    
    
    # 9.__item__系列(4个)
    # __getitem__ __setitem___ __delitem__ 对对象做类似于字典的(增删改查)触发__item__系列
    class Foo:
        def __init__(self,name):
            self.name=name
    def __getitem__(self, item):
        # print(item)
        # print(666)
        return self.__dict__[item]
    
    def __setitem__(self, key, value):
        # self.__dict__[key]=value
        print(key)
        print(value)
    
    def __delitem__(self, key):
        print(\'del obj[key]时,我执行\')
    
    f1=Foo(\'zhangsan\')
    f1[\'age\']
    f1[1] = 2
    del f1[1]
    
    
    # 10.__enter__ __exit__  with 上下文管理(2个)
    class A:
    
        def __init__(self, text):
            self.text = text
    
        def __enter__(self):  # 开启上下文管理器对象时触发此方法
            self.text = self.text + \'您来啦\'  # 第一步
            print(11111)
            return self  # 必须!!!将实例化的对象返回f1
    
        def __exit__(self, exc_type, exc_val, exc_tb):  # 执行完上下文管理器对象f1时触发此方法
            print(333)  # 第三步
            self.text = self.text + \',这就走啦\'
    
    with A(\'大爷\') as f1:
        print(2222)
        print(f1.text)  # 第二步
    print(f1.text)  # 第四步
    
    
    
    # 11.__iter__  for循环会触发此方法
    class A:
        def __init__(self,name):
            self.name = name
    
        def __iter__(self):
            for i in range(10):
                yield i
    
    obj = A(\'张三\')
    for i in obj:
        print(i)
    
    # 12.__getattr__(self,item),__setattr__(self,key,value),__delattr__ 
    #   obj.属性会触发__getattr__(self,item)方法
    #   obj.属性=123 会触发__setattr__(self,key,value)   
    #   del obj.属性 就会触发__delattr__ 此方法

     

  • def func1():
        pass
    class A:
        def func(self):
            pass
    print(func1)
    print(A.func)
    obj = A()
    print(obj.func)
    
    # 结果:
    <function func1 at 0x000000A9C59C1EA0>
    <function A.func at 0x000000A9C75DE268>
    <bound method A.func of <__main__.A object at 0x000000A9C744D4A8>>
    

以上是关于、接口与类的区别;的主要内容,如果未能解决你的问题,请参考以下文章

接口和抽象类的区别

java中GregorianCalendar类与Calendar类的关系与区别?

抽象类与接口的区别

java接口和类有啥区别?

python 面向对象专题:元类type反射函数与类的区别特殊的双下方法

python 面向对象专题:元类type反射函数与类的区别特殊的双下方法