精华内容
下载资源
问答
  • Python多继承与super使用详解

    万次阅读 多人点赞 2018-08-17 12:51:38
    多继承时,相对于使用类名.__init__方法,要把每个父类全部写一遍, 而使用super方法,只需写一句话便执行了全部父类的方法,这也是为何多继承需要全部传参的一个原因 3.3单继承使用super调用父类方法 class ...

    Python虽然支持多继承,但是python支持的多继承也是有限的。

    0.问题的提出

    • 如果不同的父类中存在 同名的方法子类对象在调用方法时,会调用哪一个父类中的方法呢?

    Python 中的 MRO —— 方法搜索顺序

    • Python 中针对  提供了一个内置属性 __mro__ 可以查看方法搜索顺序
    • MRO 是 method resolution order,主要用于在多继承时判断 方法、属性 的调用 路径
    print(C.__mro__)  #C是多继承后的类名
    

    输出结果

    (<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)
    
    • 在搜索方法时,是按照 __mro__ 的输出结果 从左至右 的顺序查找的
    • 如果在当前类中 找到方法,就直接执行,不再搜索
    • 如果 没有找到,就查找下一个类 中是否有对应的方法,如果找到,就直接执行,不再搜索
    • 如果找到最后一个类,还没有找到方法,程序报错

    1.多继承的使用

    #1.多继承:子类有多个父类
    
    class Human:
        def __init__(self, sex):
            self.sex = sex
    
        def p(self):
            print("这是Human的方法")
    
    
    class Person:
        def __init__(self, name):
            self.name = name
    
        def p(self):
            print("这是Person的方法")
    
        def person(self):
            print("这是我person特有的方法")
    
    
    class Teacher(Person):
        def __init__(self, name, age):
            super().__init__(name)
            self.age = age
    
    
    class Student(Human, Person):
        def __init__(self, name, sex, grade):
        #要想调用特定父类的构造器可以使用父类名.__init__方式。多继承使用super,会有一个坑,具体参考后面
           Human.__init__(self,sex)
           Person.__init__(self,name)
           self.grade = grade
    
    
    class Son(Human, Teacher):
        def __init__(self, sex, name, age, fan):
            Human.__init__(self, sex)
            Teacher.__init__(self, name, age)
            self.fan = fan
    
    
    # ------创建对象 -------------
    stu = Student("tom", "male", 88)
    print(stu.name,stu.sex,stu.grade)
    stu.p()  # 虽然父类Human和Person都有同名P()方法 ,但是调用的是括号里的第一个父类Human的方法
    
    
    son1 = Son("jerry", "female", 18, "打球")
    son1.person()  # 可以调用父类的父类的方法。
    son1.p()  # 子类调用众多父类中同名的方法,按继承的顺序查找。
    =====================================================================================
    tom male 88
    这是Human的方法
    这是我person特有的方法
    这是Human的方法

    总结:1.需要注意圆括号中继承父类的顺序,若是父类中有相同的方法名,而在子类使用时未指定,python从左至右搜索 即方法在子类中未找到时,从左到右查找父类中是否包含方法。

               2.支持多层父类继承,子类会继承父类所有的属性和方法,包括父类的父类的所有属性 和 方法。

    2.多继承的使用注意事项     

    #1.多继承子类对父类构造方法的调用
    class Human:
        def __init__(self,sex):
            self.sex = sex
        def p(self):
            print("这是Human的方法")
        def str1(self):
            print("this si"+str(self.sex))
    
    class Person:
        def __init__(self,name):
            self.name = name
        def p(self):
            print("这是Person的方法")
        def person(self):
            print("这是我person特有的方法")
    
        def str2(self):
            print( "this is:" + str(self.name))
    
    class Student(Human,Person): #注意子类如果没有构造方法时,按括号内父类的继承顺序去继承父类构造方法,只继承一个
        def prin(self):
            print("student")
    #------创建对象 -------------
    #stu1=Studnent("男","tom")报错。
    stu = Student("sex") #这里继承的是Huma的构造方法。
    stu.p()
    stu.str1() 
    #stu.str2()报错,因为即使human和person都是一个参数的构造方法,但是这里继承调用的是第一个Human的构造方法
    ====================================================================================
    这是Human的方法
    this sisex

      总结:子类从多个父类派生,而子类又没有自己的构造函数时,

    (1)按顺序继承,哪个父类在最前面且它又有自己的构造函数,就继承它的构造函数;

    (2)如果最前面第一个父类没有构造函数,则继承第2个的构造函数,第2个没有的话,再往后找,以此类推。

    3.多继承时使用super调用父类属性方法的注意事项

    3.1不使用super调用父类方法,使用父类名.方法名的形式。

    class Parent(object):
        def __init__(self, name):
            print('parent的init开始被调用')
            self.name = name
            print('parent的init结束被调用')
    
    class Son1(Parent):
        def __init__(self, name, age):
            print('Son1的init开始被调用')
            self.age = age
            Parent.__init__(self, name) #直接使用父类名.方法名的方式调用父类的__init__方法
            print('Son1的init结束被调用')
    
    class Son2(Parent):
        def __init__(self, name, gender):
            print('Son2的init开始被调用')
            self.gender = gender
            Parent.__init__(self, name) #
            print('Son2的init结束被调用')
    
    class Grandson(Son1, Son2):
        def __init__(self, name, age, gender):
            print('Grandson的init开始被调用')
            Son1.__init__(self, name, age)  # 单独调用父类的初始化方法
            Son2.__init__(self, name, gender)
            print('Grandson的init结束被调用')
    
    gs = Grandson('grandson', 12, '男') 
    print('姓名:', gs.name)
    print('年龄:', gs.age)
    print('性别:', gs.gender)
    
    '''执行结果如下:
    Grandson的init开始被调用
    Son1的init开始被调用
    parent的init开始被调用
    parent的init结束被调用
    Son1的init结束被调用
    Son2的init开始被调用
    parent的init开始被调用
    parent的init结束被调用
    Son2的init结束被调用
    Grandson的init结束被调用
    姓名: grandson
    年龄: 12
    性别: 男
    '''

    注意:上面代码里当在子类中通过父类名调用时,parent被执行了2次

    3.2 使用super调用父类中的方法,注意分析程序的执行顺序。

    class Parent(object):
        def __init__(self, name, *args, **kwargs):  # 为避免多继承报错,使用不定长参数,接受参数
            print('parent的init开始被调用')
            self.name = name
            print('parent的init结束被调用')
    
    class Son1(Parent):
        def __init__(self, name, age, *args, **kwargs):  # 为避免多继承报错,使用不定长参数,接受参数
            print('Son1的init开始被调用')
            self.age = age
            super().__init__(name, *args, **kwargs)  # 为避免多继承报错,使用不定长参数,接受参数
            print('Son1的init结束被调用')
    
    class Son2(Parent):
        def __init__(self, name, gender, *args, **kwargs):  # 为避免多继承报错,使用不定长参数,接受参数
            print('Son2的init开始被调用')
            self.gender = gender
            super().__init__(name, *args, **kwargs)  # 为避免多继承报错,使用不定长参数,接受参数
            print('Son2的init结束被调用')
    
    class Grandson(Son1, Son2):
        def __init__(self, name, age, gender):
            print('Grandson的init开始被调用')
            # 多继承时,相对于使用类名.__init__方法,要把每个父类全部写一遍
            # 而super只用一句话,执行了全部父类的方法,这也是为何多继承需要全部传参的一个原因
            # super(Grandson, self).__init__(name, age, gender) 效果和下面的一样
            super().__init__(name, age, gender)
            print('Grandson的init结束被调用')
    
    print(Grandson.__mro__) #搜索顺序
    
    gs = Grandson('grandson', 12, '男')
    
    print('姓名:', gs.name)
    print('年龄:', gs.age)
    print('性别:', gs.gender)
    
    '''结果如下:
    (<class '__main__.Grandson'>, <class '__main__.Son1'>, <class '__main__.Son2'>, <class '__main__.Parent'>, <class 'object'>)
    Grandson的init开始被调用
    Son1的init开始被调用
    Son2的init开始被调用
    parent的init开始被调用
    parent的init结束被调用
    Son2的init结束被调用
    Son1的init结束被调用
    Grandson的init结束被调用
    姓名: grandson
    年龄: 12
    性别: 男
    '''

     注意:在上面模块中,当在子类中通过super调用父类方法时,parent被执行了1次。

    super调用过程:上面gs初始化时,先执行grandson中init方法, 其中的init有super调用,每执行到一次super时,都会从__mro__方法元组中顺序查找搜索。所以先调用son1的init方法,在son1中又有super调用,这个时候就就根据__mro__表去调用son2的init,然后在son2中又有super调用,这个就根据mro表又去调用parent中的init,直到调用object中的init.  所以上面的打印结果如此,要仔细分析执行过程。

    尖叫提示:

    1.  super().__init__相对于类名.__init__,在单继承上用法基本无差
    2. 但在多继承上有区别,super方法能保证每个父类的方法只会执行一次,而使用类名的方法会导致方法被执行多次,具体看前面的输出结果
    3. 多继承时,使用super方法,对父类的传参数,应该是由于python中super的算法导致的原因,必须把参数全部传递,否则会报错
    4. 单继承时,使用super方法,则不能全部传递,只能传父类方法所需的参数,否则会报错
    5. 多继承时,相对于使用类名.__init__方法,要把每个父类全部写一遍, 而使用super方法,只需写一句话便执行了全部父类的方法,这也是为何多继承需要全部传参的一个原因

    3.3单继承使用super调用父类方法

    class Parent(object):
        def __init__(self, name):
            print('parent的init开始被调用')
            self.name = name
            print('parent的init结束被调用')
    
    class Son1(Parent):
        def __init__(self, name, age):
            print('Son1的init开始被调用')
            self.age = age
            super().__init__(name)  # 单继承不能提供全部参数
            print('Son1的init结束被调用')
    
    class Grandson(Son1):
        def __init__(self, name, age, gender):
            print('Grandson的init开始被调用')
            super().__init__(name, age)  # 单继承不能提供全部参数
            print('Grandson的init结束被调用')
    
    gs = Grandson('grandson', 12, '男')
    print('姓名:', gs.name)
    print('年龄:', gs.age)

    统一声明:关于原创博客内容,可能会有部分内容参考自互联网,如有原创链接会声明引用;如找不到原创链接,在此声明如有侵权请联系删除哈。关于转载博客,如有原创链接会声明;如找不到原创链接,在此声明如有侵权请联系删除哈。

    展开全文
  • ES6中class详解,class的constructor以及super使用 (**第一次使用markdown编辑呀,一个字,爽!) 下面开始正文的介绍: 1.定义 Constructor是一种用来 创建和初始化class类创建的对象 的特殊方法,一般写在class类...

    ES6中class详解,class的constructor以及super使用

    下面开始正文的介绍:

    1.定义

    Constructor是一种用来 创建和初始化class类创建的对象 的特殊方法,一般写在class类的方法里面,使类创建出来的新对象可以继承到class类上面绑定的方法以及属性, es6类中的constructor构造方法对应的是es5中的构造函数。

    • 注意:【在一个class类中只能有一个constructor的方法名,多余一个就会报错】

    例如:

    class Person {
    	constructor () {
    		this.name = ‘Lily’
    	}
    	showName () {
    		console.log('Liming')
    	}
    }
    
    var aa = new Person();
    
    aa.showName(); //'Liming'
    console.log(aa.name); //‘Lily’
    
    • 注意:若没有显式的指定constructor函数,则会添加一个默认的空的constructor这个方法
    • 注意: 在constructor中的this指的是实例对象

    2.es6中的class

    class属于es6中的一种语法糖,使用的 例子:

    //es5写法
    function Point(x, y) {
      this.x = x;
      this.y = y;
    }
    
    Point.prototype.toString = function () {
      return '(' + this.x + ', ' + this.y + ')';
    };
    var p = new Point(1, 2);
    
    //es6写法
    class Point {
      constructor(x, y) {
        this.x = x;
        this.y = y;
      }
    	toString() {
        return '(' + this.x + ', ' + this.y + ')';
      }
    }
    

    在es6中定义类的方法不需要加function这个关键字

    //这两者是等价的
    Point === Point.prototype.constructor //true
    
    • 注意:class类本身就是函数,并且自身就指向它的构造函数,类上所有的方法实际上都是定义在类的prototype属性上,当然也包括constructor()方法。所以当向类上添加方法时,要添加在类的prototype属性上,可以使用Object.assign()方法同时添加多个。

    举个?:

    class Point {
      constructor(){
        // ...
      }
    }
    
    Object.assign(Point.prototype, {
      toString(){},
      toValue(){}
    });
    
    • 注意:在类中定义的方法,如果前面加上static关键字,则表明这个方法不会被实例化出来的新对象所继承,实例化的对象是无法调用到的,而是要通过类本身来调用,这样的方法称之为 静态方法
    • 此时,若静态方法中含有this,指向的并不是实例化的新对象了,而是指向类本身。

    -可以使用extends来继承父类上面的方法,并且父类上面的静态方法也可以继承到,例子如下:

    //子类继承父类的写法
    class Bar {
    	static sayAge () {
    		console.log('19')
    	}
    }
    
    class Foo extends Bar {
    }
    Foo.sayAge() //'19'
    

    3.constructor的详解

    constructor默认会返回this这个实例对象,也可以指定返回另一个对象,constructor会在类实例化一个新对象时,自动调用这个方法

    4.super关键字

    对象函数中的this指向的是当前的函数所在的对象,而super指向的是当前函数所在对象的原型,比this更深了一个层次。在子类的构造函数中调用super(),相当于调用父类的constructor。可以举个?:

    const proto = {
      foo: 'hello'
    };
    
    const obj = {
      foo: 'world',
      find() {
        return super.foo;
      }
    };
    
    Object.setPrototypeOf(obj, proto);//使用setPrototypeOf给obj设置原型对象为proto
    obj.find() // "hello"
    

    注意:super用来表示原型对象时,只能用在对象的方法中,用在其他地方都会报错。super的常用场景,比如当子类重写了父类的某个同名方法或者属性后,如果这时还想在子类中调用这个父类的这个同名方法或属性,就可以直接使用super关键字指向父类,调用这个父类原有的方法或者属性

    js引擎只在对象的方法中识别super,对于原型对象上的realName属性,super.realName === object.getPrototypeOf(this).realName

    关于super中的this指向

    注意:当使用super指向原型对象中的一个方法时,方法中的this不指向原型对象,而是指向当前所存在的子类对象。

    父子类关系时,子类中的this问题
    • 当子类在extends继承父类时,若想在子类中使用constructor构造函数,则必须先在子类的constructor中调用super(),(若父类的constructor函数有参数传入,那么这个时候需要在super中传入参数,即super(参数)),这一步相当于先调用父类的constructor函数,无论父类中有没有写constructor函数,都要调用super()。(因为前面讲过父类会隐式的创建一个空的constructor函数)

    注意:子类在继承父类时,子类中是找不到this的,没有自己的this对象,只能使用super继承父类中的this对象,然后在加工。
    即在ES6的继承,需要先创建父类的this,子类调用super继承父类的this对象,然后再用子类的构造函数对this进行加工。
    这里另外说一下与es5继承方式的区别:
    es5的继承,实质是先创造子类的实例对象 this ,然后再将父类的方法添加到 this 上面( Parent.apply(this) )

    举例如下

    class Demo{
    	constructor(x,y) {
    	     this.x = x;
    		 this.y = y;
    	}
     }
    
    
    class Demo2 extends Demo{
    	constructor(x,y){
    		 this.x = x;		//this is not defined
    	 }
     }
    

    应该修改为:

     
    class Demo2 extends Demo{
    	constructor(x,y){
    		super(x,y);
    		console.log(super.x); //undefined
    		console.log(this.x); //这时候this是可以找到的,可以new一个实例对象,给x,y赋值试一下
    	}
    }
    
    展开全文
  • 关于this和super使用的JAVA面试试题

    千次阅读 2008-11-09 11:10:00
    因为子类中的成员变量或方法名优先级高,所以子类中的 同名成员变量或方法就隐藏了超类的成员变量或方法,但是我们如果想要使用超类中的这个成员变量或方法,就需要用到super。请看下面的类。  class Country  {...
    面试例题1:下面程序的结果是什么?[Trend公司面试题]
         class Tester
         {
             int var;
             Tester(double var)
             {
                 this.var = (int)var;     
             }   
             Tester(int var)
             {
                 this("hello");
             }  
             Tester(String s)
             {
                 this();
                 System.out.println(s);
             }
             Tester()
             {
                 System.out.println("good-bye");
             }  
             public static void main(String[] args)
             {
                 Tester t = new Tester(5);
             }
         }

         答案:
         good-bye
    hello

        扩展知识(变量的内存分配情况)

         在Java中 有两个非常特殊的变量:this和super,这两个变量在使用前都是不需要声明的。this变量使用在一个成员函数的内部,指向当前对象,当前对象指的 是调用当前正在执行方法的那个对象。super变量是直接指向超类的构造函数,用来引用超类中的变量和方法。因此它们都是非常有用的变量。下面介绍一下 this的使用方法。
         先看下面的一段代码。
         class PersonInformation
         {
             String name,gender,nationality,address;
             int age;
             void PersonInformation(String p_name,String p_gender,String
             p_nationality,String p_address,int p_age)
             {
                 name=p_name;
                 gender=p_gender;
                 nationality=p_nationality;
                 address=p_address;
                 age=p_age;
             }
         }

         在PersonInformation()函数中这个对象的方法提示可以直接访问对象的成员变量,而且在同一个范围中,定义两个相同的名字的局部变量是不 允许的。如果确实想使类的成员变量与方法的参数或方法自己定义的局部变量同名的话,就需要想一种方法使成员变量与跟它同名的方法参数或局部变量区分开来, 这就要使用到this变量。下面改写一下上面的代码,使PersonInformation类的构造函数的每个参数都有与对象成员变量相同的名字,而成员 变量的初值由参数给出。
         class PersonInformation
         {
             String name,gender,nationality,address;
             int age;
             void PersonInformation(String name,String gender,String nationality,String address,int age)
             {
                 this.name=name;
                 this.gender=gender;
                 this.nationality=nationality;
                 this.address=address;
                 this.age=age;
             }
         }

         从上例中可以看出,该构造函数中必须使用this。this在方法体中用来指向引用当前正在执行方法的那个对象实例。this变量的类型总是为包含前执行 方法的类。在上例中,我们要区别参数name和成员变量name,写成name=name显然是不允许的。在参数或局部变量名与类成员变量名相同的时候, 由于参数或局部变量的优先级高,这样在方法体中参数名或局部变量名将隐藏同名的成员变量,因此,为了指明成员变量,必须使用this显式地指明当前对象。

         有时候会遇到这种情况,全面地访问当前对象,而不是访问某一个个别的实例对象,此时也可以使用this,并利用Java中 的toString ()方法(它能够返回一个描述这个对象的字符串)。如果把任何一个对象传递到System.out.println方法中,这个方法调用这个对象的 toString方法,并打印出结果字符串,所以,可以用System.out.println(this)方法来打印出固有参数的当前状态。

         this还有一个用法,就是构造函数的第一个语句,它的形式是this(参数表),这个构造函数就会调用同一个类的另一个相对的构造函数。请看下面的例子。
         class UserInfo
         {
             public UserInfo(String name)
             {
                 this(name,aNewSerialNumber);
             }
             public Userinfo(String name,int number)
             {
                 userName=name;
                 userNumber=number;
             }
         }

         如果调用UserInfor newinfotable = new UserInfo("Wayne Zheng"),就会自动调用UserInfo(String name,int number)构造函数。
         可见,熟练掌握this在Java程序设计过程中是非常重要的。

        面试例题2:以下代码的运行结果是   。[Advantech公司2005年12月面试题]
         class Base{
             int i;
             Base(){
                 add(1);
                 System.out.println(i);
             }
             void add(int v){
                 i+=v;
                 System.out.println(i);
             }
             void print(){
                 System.out.println(i);
             }
         }
         class MyBase extends Base{
             MyBase(){
                 add(2);
             }
             void add(int v){
                 i+=v*2;
                 System.out.println(i);
             }
         }
         public class TestClu {
             public static void main(String[] args) {
                 go(new MyBase());
                 //System.out.println();
             }
             static void go(Base b){
                 b.add(8);
                 //b.print();
             }
         }
         A.12   B.11   C.22   D.21

         解析:
         程序流程是这样的:在主函数中,首先执行new MyBase(),在这个过程中,子类会首先调用父类的构造函数;在父类的构造函数Base()中执行add()方法。这里需要注意,这个add方法由于 是在新建MyBase对象时调用的,将会首先查找MyBase类中是否有此方法。所以,Base()函数中的add(1)实际上是:

        //add(1)调用的是Mybase类的方法??真奇怪

         void add(int v)
         {
             i+=v*2;      System.out.println(i);
         }

         此时i的值即为2。在打印两个2之后,父类构造函数执行完毕,执行子类的构造函数,即MyBase(),这里的add(2)当然也是子类的。i的值就变为了6。
         最后执行go函数,i即为22。
         答案:C

    --------------------------------------------------------super 分割线-----------------------------------------------------------

    ——此文章摘自《Java程序员面试宝典》定价:46元 特价:38.9元 购买>>?m_id=dangdang&a_id=A100040392&l=99999&l_type2=0

        面试例题1:以下代码的输出结果是下列哪个选项?[Sun公司2005年面试题]
         class Base{Base(){
             System.out.println("Base");
             }
         }
         public class Checket extends Base{

            Checket(){   
             System.out.println("Checket");
             super();
             }

            public static void main(String argv[]){
                 Checket c = new Checket();
                 // super();
             }
         }

         A.Compile time error
         B.Checket followed by Base
         C.Base followed by Checket
         D.runtime error

         解析:这是一个考查super构造函数的面试例题。子类的构造函数如果要引用super的话,必须把super放在函数的首位,不然会出现这样的报错:
         Checket.java:10: call to super must be first statement in constructor
         super();
         如果一定要引用super构造函数,则必须把super()放在前面,代码如下。
         class Base{Base(){
             System.out.println("Base");
         }}
         public class Checket extends Base{ Checket(){
             super();
             System.out.println("Checket");
             } public static void main(String argv[]){
                 Checket c = new Checket();
             // super();
             }
         }

         答案:会出现编译报错,选项A

        面试例题2:Java里在类中用super调用父类构造函数时,为什么调用语句必须是子类的第一条语句?[Siemens公司2005年面试题]

         答案:如果想用super继承父类构造的方法,但是没有放在第一行的话,那么在super之前的语句,肯定是为了满足自己想要完成某些行为的语句,但是又 用了super继承父类的构造方法。那么以前所做的修改就都回到以前了,就是说又成了父类的构造方法了。如下面的程序所示。
         class Father
         {
             public Father()
             {String name=null;
             int age=0;}
         }
         class Son extends Father
         {
             public Son()
             {String name="学生";
             super();       //调用父类的构造函数,此时name又变回null,所以super()必须放第一条语句
             }
         }

         扩展知识(Java中的super类)

         在Java中,有时还会遇到子类中的成员变量或方法与超类(有时也称父类)中的成员变量或方法同名。因为子类中的成员变量或方法名优先级高,所以子类中的 同名成员变量或方法就隐藏了超类的成员变量或方法,但是我们如果想要使用超类中的这个成员变量或方法,就需要用到super。请看下面的类。
         class Country
         {
             String name;
             void value()
             {
                 name="China";
             }
         }
         在下面的子类中,子类的成员变量和方法隐藏了超类的成员变量name和方法value()。
         class City extends Country
         String name;
         void value()
         {
             name="Hefei";
             super.value();

          System.out.println(name);
             System.out.println(super.name);
         }
         为了在子类中引用超类中的成员变量name和方法value(),在代码中使用了super、super.name和super.value(),所以显示的结果为:
         Hefei
         China

         如果想要使用超类的构造函数,则应当使用super(参数列表)的形式

        面试例题3:给定下面的代码,哪个选项在替代"//Here"后可以被编译并且改变变量oak的值?
         class Base{
             static int oak=99;
         }
         public class Doverdale extends Base{
             public static void main(String argv[]){
                 Doverdale d = new Doverdale();
                 d.amethod();
            }
            public void amethod(){
                 //Here
            }      
         }

         A.super.oak=1;
         B.oak=33;
         C.Base.oak=22;
         D.oak=50.1;

         解析:因为变量oak被声明是静态的,如果它存在只能有一个本体,则它可以通过本类的名字或者通过定义本类的任何一个实例被改变。


         答案:A、B、C

        面试例题4:当编译和运行下列代码时会发生下列哪种情况?     
         class Base{
             Base(){
                 System.out.println("Base");
            }
         }   
         public class Checket extends Base{
             public static void main(String argv[]){
                 Checket c = new Checket();
                 super();
            }   
             Checket(){
                 System.out.println("Checket");
             }      
         }

         A.Compile time error
         B.Checket followed by Base
         C.Base followed by Checket
         D.runtime error

         解析:
         用Sun的JDK运行会出现下列出错信息。
         "Only constructors can invoke constructors"

         Checket作为一个构造方法应该在调用时从最老的祖先类开始向下调用,调用super会引起程序在编译和运行时间上的错误。

        Java中的关键字super:调用父类的属性,一个类中如果有int x属性,如果其子类中也定义了int x属性的话,在子类中调用父类的x属性时应用super.x=6,表示该x是引用的父类的属性,而要表示子类中的x属性的话,使用this.x。

         this和super:在Java中, this通常指当前对象,super则指父类的对象。若想要引用当前对象的某种东西,比如当前对象的某个方法,或当前对象的某个成员,便可以利用this 来实现这个目的。当然,this的另一个用途是调用当前对象的另一个构造函数。如果想引用父类的某种东西,则非super莫属。

         Java里在子类中用super调用父类构造函数时,调用函数必须放在子类的第一条语句的位置,如果想用super继承父类构造的方法,但是没有放在第一 行的话,那么在super之前的语句,也许是为了满足自己想要完成某些行为的语句,但是又用了super继承父类的构造方法,以前所做的修改就都回到以前 了,也就是说又成了父类的构造方法了。

    展开全文
  • Java中super()的使用

    万次阅读 多人点赞 2018-09-12 22:10:18
    1.super()的使用实例 一一一子类重写父类的方法 2.super()的使用实例 一一一子类重写父类的变量 3.super()的使用实例 一一一在子类的构造方法中  4.关于构造方法中super() 第一种情况:编译不通过 第二种情况...

    目录

    1.super()的使用实例 一一一子类重写父类的方法

    2.super()的使用实例 一一一子类重写父类的变量

    3.super()的使用实例 一一一在子类的构造方法中

     4.关于构造方法中super()

    第一种情况:编译不通过

    第二种情况:编译不通过

    第三种情况:成功编译通过


     

    1.super()的使用实例 一一一子类重写父类的方法

    public class A {
    	
    	private String nameA="A";
    	
    	public void getName() {
    		System.out.println("父类"+nameA);
    	}
    	public static void main(String[] args) {
    	}
    	
    }
    
    
    public class B extends A{
    	private String nameB="B";
    	
    	@Override
    	public void getName() {
    		System.out.println("子类"+nameB);
    		super.getName();
    	}
    	
    	public static void main(String[] args) {
    		B b=new B();
    		b.getName();
    	
    	}
    }

    运行结果:

    结果分析:

    在子类B中,我们重写了父类的getName方法,如果在重写的getName方法中我们去调用了父类的相同方法,必须要通过super关键字显示的指明出来。

    如果不明确出来,按照子类优先的原则,相当于还是再调用重写的getName()方法,此时就形成了死循环,执行后会报java.lang.StackOverflowError异常。如下图所示:

    2.super()的使用实例 一一一子类重写父类的变量

    public class A {
    	
    	 String nameA="A";
    
    }
    
    public class B extends A{
    	 String nameA="B";
    	
    	
    	public void getName() {
    		System.out.println("子类"+nameA);
    		System.out.println("父类"+super.nameA);
    	}
    	
    	public static void main(String[] args) {
    		B b=new B();
    		b.getName();
    	
    	}
    }
    

    运行结果:

    此时子类B中有一个和父类一样的字段(也可以说成父类字段被隐藏了),为了获得父类的这个字段我们就必须加上super,如果没有加,直接写成name = name;不会报错,只是会警告,表示此条语句没有任何意义,因为此时都是访问的子类B里面的那么字段。

    我们通过super是不能访问父类private修饰的变量和方法的,因为这个只属于父类的内部成员,一个对象是不能访问它的private成员的。

     

    3.super()的使用实例 一一一在子类的构造方法中

    编译器会自动在子类构造函数的第一句加上 super(); 来调用父类的无参构造器;此时可以省略不写。如果想写上的话必须在子类构造函数的第一句,可以通过super来调用父类其他重载的构造方法,只要相应的把参数传过去就好。

     

    因此,super的作用主要在下面三种情况下:

    1、调用父类被子类重写的方法;

    2、调用父类被子类重定义的字段(被隐藏的成员变量);

    3、调用父类的构造方法;

    其他情况,由于子类自动继承了父类相应属性方法,关键字super可以不显示写出来。

     4.关于构造方法中super()

    第一种情况:编译不通过

     

    分析:

    如果一个类中没有写任何的构造方法,JVM会生成一个默认的无参构造方法。在继承关系中,由于在子类的构造方法中,第一条语句默认为调用父类的无参构造方法(即默认为super(),一般这句话省略了)。所以当在父类中定义了有参构造函数,都是没有定义无参构造函数时,IDE会强制要求我们定义一个相同参数类型的构造器。

    在本例中JVM默认给B加了一个无参构造方法,而在这个方法中默认调用了super(),但是父类中并不存在该构造方法

    第二种情况:编译不通过

    同样编译错误,相同的道理,虽然我们在子类中自己定义了一个构造方法,但是在这个构造方法中还是默认调用了super(),但是父类中并不存在该构造方法

    第三种情况:成功编译通过

    public class A {
    	public A(String s) {
    		
    	}
    
    }
    
    public class B extends A{
    	public B(String s) {
    		super(s);
    	}
    }
    

    分析:

    所以,只要记住,在子类的构造方法中,只要里面没有显示的通过super去调用父类相应的构造方法,默认都是调用super(),即无参构造方法,因此要确保父类有相应的构造方法。

     

     转载:https://blog.csdn.net/shakespeare001/article/details/51388516

     

    展开全文
  • super关键字的使用

    千次阅读 2018-12-06 11:06:14
    super关键字直接引用父类的实例变量通过 super 来调用父类方法使用super来调用父类的构造函数 java中的super关键字是一个引用变量,用于引用直接父类对象。 super关键字用法如下: 可以用来引用直接父类的实例变量...
  • Java中super关键字及super()的使用

    千次阅读 多人点赞 2020-07-06 22:52:15
    super关键字的使用: (1)super是一个关键字; (2)super和this很类似,我们对比着学习。 先复习一下this关键字的使用。 this关键字: this能出现在实例方法和构造方法中; this的语法是“this.”和“this()”; ...
  • java super使用

    千次阅读 2016-04-30 15:57:45
    继承,是有关联性的“父子”关系,在java中只可以单继承,java中的super是调用父类的构造函数,super不写的时候,在每次子类实现的时候都是默认super(),所以super有时是在初始化构造函数时使用。 例子: ...
  • super()在Java中的使用方法

    千次阅读 2020-04-02 18:58:51
    super使用总共有三种 1. 即是上文的所说的子类对父类方法的重写的情况下,存在子类的方法里面存在父类的参与 用 super. 即可以使用(此时的super.某方面类似于this. 。只是this指向对象,而super指向父类)。 2.调用...
  • java-继承super使用

    千次阅读 2014-11-30 00:19:15
    java-继承,super使用
  • SuperSocket使用问题收集

    千次阅读 2016-10-17 12:00:31
    SuperSocket使用问题收集
  • super关键字的简单使用

    千次阅读 2019-06-02 20:35:43
    java中子类不继承父类的构造方法,但是我们需要使用到父类的构造方法时可以利用super关键字来调用父类的构造方法,super调用父类的构造方法例子如下 package test; class Student{ int number; String name; ...
  • supersocket的自定义协议里面,如果遇到一些错误的数据,或者说毫无意义的数据,那么对于 FixedHeaderReceiveFilter 协议,后面正确格式的数据也收不到了,就好像发送错误数据的客户端被拉黑了一样,收不到任何...
  • super()函数的使用

    千次阅读 多人点赞 2018-11-10 14:51:59
    文章目录说明继承使用super()真实的super()总结感谢 018.11.10 说明 一些Python入门书并没有讲清楚super()函数应该怎么用,只在说继承知识点的时候顺便一笔带过。为此我糊涂了好久、好久…… 继承 Python中的继承很...
  • ES6中super使用

    千次阅读 2016-05-08 13:43:45
    第一种方式有二点要注意,在构造函数中用this之前,必须先使用super。 另一点算是super的BUG吧。当父类和子类都重写了构造函数时,如果在子类构造函数中设置类属性~如:this.prop = [];将会报错。具体见:...
  • 类继承中super使用

    千次阅读 2015-08-19 00:00:48
    使用super访问父类的域和方法 正是由于继承,使用this可以访问父类的域和方法,但有时为了明确地指明父类的域和方法,就要用关键字super。 例如:父类Person中一个字段age,在子类Student中使用age, this.age, ...
  • Super()使用方法

    千次阅读 2019-05-20 21:28:36
    super 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是如果使用多继承,会涉及到查找顺序(MRO)、重复调用(钻石继承)等种种问题。 MRO 就是类的方法解析顺序表, 其实也就是继承...
  • Unity 超级列表SuperScrollview使用Demo

    千次阅读 2019-09-29 17:46:07
    首先,说一下使用SuperScrollview的基本配置: 创建一个scrollview,然后把横纵滑动条设置可配置的,然后再加上LoopListView2代码,如下: 然后我们创建四个代码类: 1、数据类: 2、数据管理类方便增删查改:...
  • Lombok 的 @EqualsAndHashCode(callSuper = false) 的使用

    万次阅读 多人点赞 2019-05-10 13:56:01
    但是,这个参数,callsuper = false 有问题吗? 你在使用这个注解的时候,确定知道“为什么要重写hashcode和equals方法吗?” 先看下面的测试。 两个model的代码我就截图啦:父类 TV.java 和 子类 小米TV.java,...
  • java中super关键字的使用

    千次阅读 2013-04-07 20:02:11
    直接使用super()加上父类构造函数所需要的参数,系统根据super()参数个数和类型自动匹配父类中的构造函数。 *在调用子类的默认无参数构造函数创建对象的时候,系统会自动的去调用父类的无参构造函数。 2.调用...
  • I . 子类调用父类总结 II . 子类调用父类方法 ( super ) III . 子类内部类调用父类方法 ( super@ ) IV . 子类选择调用不同的 父类 / 接口方法 ( super<> )
  • java中super使用

    千次阅读 2014-04-22 10:13:13
    super(parameter-list); parameter-list指定
  • AS3 Super使用

    千次阅读 2012-10-19 12:12:07
    1.super是执行父类构造函数,构造方法中如果写了程序,则会调用该程序.如果程序中的方法,子类重写了,则执行重写的方法。...还可以使用 super 前缀作为对超类的引用来调用超类的方法。如果决定在同一构造函
  • super-diamond 结合springboot的使用经验

    千次阅读 2018-08-07 16:42:55
    1. super-diamond server部署 ...git上的使用说明有点问题,括号里是我在实际使用过程中自己的改动,供参考: 下载super-diamond代码: git clone https://github.com/melin/super-diamond.git 进入super-diam...
  • Super VLAN

    千次阅读 多人点赞 2021-04-16 19:45:31
    Super VLANSuper VLAN技术背景Super VLANSuper VLAN通信规则Super VLAN使用前后对比配置案例场景基础配置Super VLAN配置验证 Super VLAN 技术背景 传统VLAN部署中,一个VLAN对应一个网段和一个VLANIF三层接口实现...
  • java super 和 this 关键字的区分和使用

    千次阅读 多人点赞 2018-10-10 16:07:46
    java super 和 this 关键字的区分和使用 在java类中使用super来调用父类中的指定操作: super可用于访问父类中定义的属性 super可用于调用父类中定义的成员方法 super可用于在子类构造方法中调用父类的构造器 ...
  • C#/.NET SuperSocket的使用

    万次阅读 2020-01-15 19:41:28
    首先安装:SuperSocket.Engine SuperSoket的三大对象: Session: 每一个用户连接就是一个Session AppServer: Socket服务器实例 Commands: 客户端向服务器发送消息的命令集合 首先在配置文件加入如下配置 <...
  • 1. 创建控制台项目,导入SuperSocket.Common、SuperSocket.SocketBase、SuperSocket.SocketEngine并添加好引用 2. 在控制台项目中添加Config文件夹及SuperSocket提供的log4net配置文件
  • SUPERSOCKET.CLIENTENGINE 简单使用

    千次阅读 2018-06-15 14:57:00
    引用 SuperSocket.ClientEngine.Core.dll和 SuperSocket.ClientEngine.Common.dll 然后 就可以使用ClientEngine了。 ClientEngine 我找了好久,只找到 AsyncTcpSession这么一个可以实例化的连接会话,那么,就用...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,130,078
精华内容 452,031
关键字:

super的使用