(25)继承中成员变量、函数中覆盖、构造函数的理解

来源:互联网 发布:如何选择净水器 知乎 编辑:程序博客网 时间:2024/06/05 11:46

一、继承思想的引出

  将学生和工人的共性描述提取出来,单独进行描述

  只要让学生和工人与单独描述的这个类有关系,就可以了。

二、继承作用

      1.提高了代码的复用性

      2.让类与类之间产生了关系,有了这个关系,才有了多态的特性

注意:①千万不能为了获得其他类的功能,简化代码而继承

           必须是类与类之间所属关系才可以继承,所属关系是  is  a

           ②java中只支持单继承,java支持多重继承

多继承容易带来安全隐患:当多个父;类中定义了相同功能,当功能内容不同时,子类对象不确定运行哪一个

但是java保留这种机制,用另一种体现形式来完成表示,多实现

例如:

class A

{

   void show(){

         System.out.println("a");

      }

}


class B

{

   void show(){

         System.out.println("b");

      }

}


class C extends A,B{}

  C c=new  C();

    c.show();//不确定调用哪个类中的同名函数

三、如何使用一个继承体系中的功能呢?

 想要使用体系,先查阅父类的描述,因为父类中定义的是该体系中共性功能。通过了解共性功能,就可以知道该体系的基本功能

这个体系已经基本可用了   

四、具体调用创建对象

在具体调用时,要创建最子类的对象。理由:①有可能父类不能创建对象(如抽象类)②创建子类对象可以使用更多的功能,也包括基本的都可以使用

三四总结:查阅父类功能,创建子类对象使用功能

五、子父类中变量的特点

类中成员:

1.变量

如果子类中出现非私有的同名成员变量时,子类要访问本类中的变量用this,子类要访问父类中的同名变量用super

super的使用和this的使用几乎一致。

this 代表的是本类对象的引用。super代表父类对象的引用

简单分三种情况:①全私有②非私有③无重名。


public class person {public String country;private String name;private int age;public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}}    public String country;    private String name;    public void study() {                System.out.println("good study");            }        public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    /*     * 子类成员和父类私有成员同名,若直接使用,使用的是子类变量this.name     * 要使用父类变量,则用到super关键字,super.name,因为一个类中定义的属性应该私有     * (private),所以要用到getter方法super.getName()     *      */    public void show() {        System.out.println(name);        System.out.println(super.getName());              //System.out.println(getName());这样写也可以    }        /*     * 子类成员和父类非私有成员同名     */    public void show1() {        System.out.println(this.country);        System.out.println(super.country);            }    /*     * 子类成员变量中无同名的,继承父的     */    public void show2() {               System.out.println(super.getAge());            }    public static void main(String[] args) {        worker w=new worker();        w.setName("张三");        /*         * 子类成员和父类私有成员同名         */        w.show();        /*         *  子类成员和父类非私有成员同名         */       w.country="cn";       w.show1();       /*        * 子类成员变量中无同名的,继承父的        */       w.show2();            }} 





2.函数

对新写功能,没啥可说的,主要说下覆盖

当子类出现和父类一模一样的函数时,当子类对象调用该函数时,会运行子类函数的内容。

如同父类的函数被覆盖一样。这种情况是函数的另一个特性:重写(覆盖)

当子类继承了父类,沿袭了父类的功能,到子类中,但是子类虽具备该功能,但是功能的内容却和父类不一致(覆盖的条件)

这时,没有必要定义新功能,而是使用覆盖特殊,保留父类的功能定义,并重写功能内容。

覆盖的作用:提高程序的扩展性

举个栗子:对(子类虽具备该功能,但是功能的内容却和父类不一致)理解

父类:人     speak(){s.o.p(“会说话”)}

子类:英国人  speak(){s.o.p(“会说英国话”)}

都是说话,没必要定义新的功能,覆盖即可

举个栗子:对提高程序的扩展性的理解

手机不断升级,不能修改源码,因为调用等会带来更多的修改。对来电显示功能进行拓展

父类:手机  show(){ s.o.p("numer")}

子类:新型手机  show(){ s.o.p("numer");

                                       s.o.p("picture");

                                         s.o.p("name");

                                        }

对函数的功能进行拓展填充

父:public void show () {
        System.out.print("country="+country);
        System.out.print("  name="+name);
        System.out.print("  age="+age);
        
    }
子:public void show () {
        super.show();//有些被覆盖函数的内容,在覆盖函数中也可以用,调用方法super.
                              若不加super就会是死循环,发生内存溢出

        System.out.print("  salary="+salary);
    }

写覆盖时的注意事项:

①子类覆盖父类,必须保证子类函数权限大于等于父类函数权限,才可以覆盖,否则编译失败

②静态只能覆盖静态的。(加载类时,非静态不加载)【知道即可,编程不用】


记住:重载:只看同名函数的参数列表

          重写:子父类方法要一模一样(“三同一不低” 子类和父类的方法名称,参数列表,返回类型必须完全相同,而且子类方法的访问修饰符的权限不能比父类低)

③编程注意一个问题

父:  int show(){执行语句;}

子:void show (  ){执行语句;}

子.show();//会出现编译错误。首先这不是覆盖,子继承父类,子类此时相当于有两个函数int  show(){} void  show(){}

虚拟机不知道执行哪个,所以出现编译错误。


3.构造函数

①特点:在对子类对象进行初始化时,父类的构造函数也会执行,那是因为子类的所有构造函数默认第一行有一条隐式的语句super()

(若重载了无参构造函数,则执行这个)

若父类重载了含参的构造函数(就不再含无参隐式了),则子类构造函数中,就不再含隐式语句super(),此时,必须指定要调用父类哪个构造函数。

②为什么子类一定要访问父类中的构造函数?

因为父类中的数据子类可以直接获取,所以子类对象在建立时,需要先查看父类是如何对这些数据初始化的。

如果要访问父类中指定的构造函数,可以通过手动定义super语句来指定(若写super()写在子构造函数的第一行)

③小应用:对访问父类中指定的构造函数,可以通过手动定义super语句来指定理解

父:class   person  

               person(String name){this.name=name;}//构造函数

             void  show(){}

子:class   strudent  extends person

               strudent(String name){

                      要执行这条语句this.name=name;,因为父类已经完成了这个函数,子类就可以继承或者在方法体中调用这个方法

                      所以可以用super(name)来完成,子构造函数内调用父构造函数不用.

                 

}

void method(){      super.show();   //子普通构造函数调用父普通构造函数, super. }

④this(),super(),若写只能写在构造函数的第一行

就出现一个问题,若两者在子类中都想写,应该怎么办?

父:person  

        person(){  执行语句;}

         person(int x) {执行语句;}

子:student

        student(){执行语句;}//含隐式的suer()

        studetn(int x){this();执行语句;}

         student s=new student(2);//其实this(),super(),都执行到了。

结论:子类的所有构造函数,默认都会访问父类中无参数的构造函数。因为子类每一个构造函数内的第一行都有一句隐式super();
          当父类中没有空参数的构造函数时,子类需要通过super语句或者this语句来指定要访问父类中的构造函数 。

当然:子类的构造函数第一行也可以手动指定this语句来访问本类的构造函数。

         子类中至少有一个构造函数会访问到父类中的构造函数






阅读全文
0 0
原创粉丝点击