1.继承

目录

2.继承

2.1.继承概念

2.1.1.面向对象三大特征

2.1.2.继承与多态关系

2.1.3.继承主要解决的问题

2.1.4.继承关系当中的特点

2.1.5.封装主要解决的问题

2.2.继承格式

2.3.继承中重复变量、方法的访问特点

2.4.继承中成员变量访问特点

2.5.子类方法中三种变量重名

2.6.继承中成员方法访问特点

2.7.继承中方法的覆盖重写

2.8.继承中覆盖重写应用

2.9.继承中构造方法访问特点

1.10.super关键字三种用法

1.11.this关键字三种用法

1.12.this与super关键字图解

1.13.java继承的三个特性


 


2.继承

2.1.继承概念

2.1.1.面向对象三大特征

2.1.2.继承与多态关系

2.1.3.继承主要解决的问题

2.1.4.继承关系当中的特点

2.1.5.封装主要解决的问题

  • 我们观察如下代码:
    • 以下的操作代码并没有出现了语法错误,但是出现了逻辑错误 (年龄-30岁)
    • 在开发中, 为了避免出现逻辑错误, 我们建议对所有属性进行封装,并为其提供setter及getter方法进行设置和取得操作。

class Person{
 String name ; // 表示姓名
 int age ; // 表示年龄
void tell(){
System.out.println("姓名:" + name + ";年龄:" + age) ;
}
};
public class Demo{
public static void main(String args[]){
Person per = new Person() ;
per.name = "张三" ;
per.age = -30 ;
per.tell() ;
}
};
  • 修改代码如下:
class Person{
private String name ; // 表示姓名
private int age ; // 表示年龄
void tell(){
System.out.println("姓名:" + getName() + ";年龄:" + getAge()) ;
}
public void setName(String str){
name = str ;
}
public void setAge(int a){
if(a>0&&a<150)
age = a ;
}
public String getName(){
return name ;
}
public int getAge(){
return age ;
}
};
public class OODemo10{
public static void main(String args[]){
Person per = new Person() ;
2.2、this
2.3、static
概述
重点:
per.setName("张三") ;
per.setAge(-30) ;
per.tell() ;
}
};

2.2.继承格式

 * 在继承的关系中,"子类就是一个父类",也就是说,子类可以被当做父类看待。
 * 例如父类是员工,子类是讲师,那么“讲师就是一个员工”,即is-a关系
 *
 * 定义父类的格式:(一个普通的类定义)
 * public class 父类名称{
 *   //...
 * }
 * 定义子类的格式:
 * public class 子类名称 extends 父类名称{
 *     //...
 * }



package demo1_extend;
//定义一个父类:员工
public class Employee {
    public void method(){
        System.out.println("方法被执行..");
    }
}

package demo1_extend;
//定义一个员工的子类:讲师
public class Teacher extends Employee{//子类继承父类内容}

package demo1_extend;
//定义员工的另一个子类:助教
public class Assistant extends Employee{ }
  
package demo1_extend;
public class Demo1 {
    public static void main(String[] args) {
        //创建一个子类对象
        Teacher teacher = new Teacher();
        //Teacher类当中虽然什么都没写,但会继承来自父类的method方法
        teacher.method();

        //创建另一个子类对象
        Assistant assistant = new Assistant();
        assistant.method();

        //实现代码复用-method方法的复用
    }
}

2.3.继承中重复变量、方法的访问特点

  • 继承关系中,变量看等号左侧,方法看等号右侧
package demo;
public class Demo01 {
    int num=1;
    public void method(){
        System.out.println(num);
    }
}
package demo;
public class Demo02 extends Demo01{
    int num=2;
    public void method(){
        int num=3;
        System.out.println(num);
        System.out.println(this.num);
    }
}
package demo;
public class DemoTest {
    public static void main(String[] args) {
        Demo02 demo01 = new Demo02();
        System.out.println(demo01.num); //2

        Demo01 demo02 = new Demo02();
        System.out.println(demo02.num); //1

        demo01.method();//3  2
        demo02.method();//3  2
    }
}

2.4.继承中成员变量访问特点

  • 在父子类的继承关系中,如果成员变量重名,则创建子类对象时,访问有两种方式:
    • 直接:通过子类对象访问成员变量.。等号左边是谁,就优先谁,没有则向上找
    • 间接:通过成员方法访问成员变量。方法属于谁(在哪定义),就优先用谁,没有则向上找
public class Fu {
    //定义成员变量(不用setter,getter,直接赋值)
    int numFu=10;
    int num=300;
    //定义成员方法
    public void methodFu(){
        //输出的是本类Fu的num,不会向下找子类
        System.out.println(num);
    }
}

package demo2_extend;
public class Zi extends Fu{
    //定义成员变量
    int numZi=20;
    int num=200;
    //定义成员方法
    public void methodZi(){
        //输出的是本类Zi的num,若本类无num,则向上找
        System.out.println(num);
    }
    public void methodFu(){
        //输出的是本类Fu的num,不会向下找子类
        System.out.println(num);
    }
}

package demo2_extend;
public class Demo01ExtendField {
    public static void main(String[] args) {
        Fu fu = new Fu(); //创建父类对象
        System.out.println(fu.numFu); //只能使用父类东西,没有任何子类内容

        Zi zi = new Zi();
        System.out.println(zi.numFu); //10 子类访问父类变量
        System.out.println(zi.numZi); //20 子类访问自身变量

        //等号左边是谁,就优先用谁
        System.out.println(zi.num); //200 zi是由Zi zi = new Zi()创建而非Fu zi=

        //这个方法是子类的,优先用子类的,没有再向上找
        zi.methodZi(); //200
        //这个方法是在父类中定义的,优先使用父类变量
        zi.methodFu(); //300

        Fu zii=new Zi();
        System.out.println(zii.num); //300 等号左边是Fu类,优先使用
        zii.methodFu();//
    }
}

2.5.子类方法中三种变量重名

  • 局部变量:直接成员变量名 访问
  • 本类成员变量:this.成员变量
  • 父类成员变量:super.成员变量
public class Fu {
    int num=10;
}

package demo3_extend;
public class Zi extends Fu {
    int num=20;
    public void method(){
        int num=30; //定义局部变量
        System.out.println(num);//30 局部变量
        System.out.println(this.num);//20 本类的成员变量
        System.out.println(super.num);//10 父类的成员变量
    }
}

package demo3_extend;
public class Demo01ExtendField {
    public static void main(String[] args) {
        Zi zi = new Zi();
        zi.method();
    }
}

2.6.继承中成员方法访问特点

  •  在父子类的继承关系中,创建子类对象,访问成员方法的规则:
    • 创建的对象是谁,就优先用谁,如果没有则向上找,即看等号右侧。
    • 即继承关系中,变量看等号左侧,方法看等号右侧
  • 注意事项:
    • 无论是成员方法还是成员变量,如果没有都是向上找父类,绝对不会向下找子类
package demo4_extend;
public class Fu {
    public void method(){
        System.out.println("父类重名方法被执行");
    }
}
package demo4_extend;
public class Zi extends Fu{
    public void method(){
        System.out.println("子类重名方法被执行");
    }
}

package demo4_extend;
public class Demo01ExtendMethod {
    public static void main(String[] args) {
        Zi zi = new Zi();
        //创建的是子类对象new Zi(),所以优先用子类方法
        zi.method();  // 输出:子类重名方法被执行

        /*这个涉及到对象的多态性,父类对象由子类实例化,
          即是对象的多态性中的一种类型之一:向上转型

          父类 父类对象=子类实例 意思就是说:我们是使用子类来实例化对象,
          而这个对象却是披上了“父类对象”的名称*/
        Fu zii=new Zi();
        zii.method();  //输出:子类重名方法被执行
    }
}

2.7.继承中方法的覆盖重写

  • 1.重写的概念: 重写(override)指在继承关系中,方法的名称一样,参数列表也一样。
  • 2.重写与重载区别:
    • 重写(Override):方法的名称一样,参数列表【也一样】
    • 重载(Overload):方法的名称一样,参数列表【不一样】
  • 3.方法重写特点:创建的子类对象,则优先用子类方法
  • 4.重写的方法需要满足的条件:
    • 1.必须保证父子类之间方法的名称相同,参数列表也相同。@Override: 写在方法前面,用来检测是不是有效的复写, 这个注解就算不写,只要满足要求,也是正确的方法复写
    • 2.子类方法的返回值类型必须【小于等于】父类方法的返回值范围。
      • 提示:Object类是所有类的公共最高父类,String类就是Object类子类
    • 3.子类方法的权限修饰符必须【大于等于】父类方法的权限修饰符
      • 提示:public>protected>(default)>private
      • 备注:(default)不是关键字default,而是什么也不是,留空

2.8.继承中覆盖重写应用

  • 不要修改老版本,在新版本中添加新功能,对于已经有的旧功能可进行覆盖重写
package demo6_extend;
//本来的老款手机
public class Phone {
    public void call(){  System.out.println("打电话");  }
    public void send(){  System.out.println("发短信");  }
    public void show(){  System.out.println("显示号码");}
}

package demo6_extend;
//定义一个新手机,使用老手机作为父类
public class NewPhone extends Phone{
    @Override
    public void show(){  //重写show方法,对老手机进行升级
        //父类中的show功能仍需要使用
        super.show();
        //自己子类中又添加其他功能
        System.out.println("显示姓名");
        System.out.println("显示头像");
    }
}

package demo6_extend;
//继承中覆盖重写的应用:给手机添加新功能
public class Test {
    public static void main(String[] args) {
        //使用老手机功能
        Phone phone = new Phone();
        phone.call();  //打电话
        phone.send();  //发短信
        phone.show();  //显示号码

        //使用新手机功能
        NewPhone newPhone = new NewPhone();
        newPhone.call();  //打电话
        newPhone.send();  //发短信
        newPhone.show();  //显示号码 显示姓名 显示头像
    }
}

2.9.继承中构造方法访问特点

  • 1.子类构造方法中有一个默认的隐含的"super()"调用,所以一定是先调用的父类的构造方法,后执行子类构造,注意隐含的super()调用的是无参构造函数。
  • 2.子类构造方法中可以通过super关键字调用父类的重载构造方法。super(参数)
  • 3.super的父类构造调用,必须是子类构造方法的第一个语句,另外不能一个子类构造调用多次super构造
  • 总结:
    • 继承中子类必须调用父类构造方法,不写则赠送super(),写了则按定义的super调用,
    • super只能有一个,还必须是第一个语句
package demo7_extend;
public class Fu {
    public Fu(){System.out.println("父类无参构造方法"); }
    public Fu(int num){   System.out.println("父类重载构造方法"); }
}

package demo7_extend;
public class Zi extends Fu{
    public Zi(){
        //子类构造方法中隐含着super()调用,调用父类的无参构造方法,若含参则自己写
        //super();
        super(20);  //规则2
        System.out.println("子类无参构造方法");
    }
    public void method(){
       // super(); 错误写法,规则3,super构造必须子类构造的第一个语句
    }
}

package demo7_extend;
//继承中,构造方法的访问特点
public class Demo01Constructor { }

1.10.super关键字三种用法

  • super关键字三种用法   super关键字访问父类内容
    • 1.在子类的成员方法中,访问父类的成员变量
    •  2.在子类的成员方法中,访问父类的成员方法
    •  3.在子类的构造方法中,访问父类的构造方法
package demo8_extend;
public class Fu {
    int num=10;
    public void method(){System.out.println("父类成员方法"); }
}

package demo8_extend;
//super关键字三种用法   super关键字访问父类内容
public class Zi extends Fu{
    int num=20;
    public Zi(){ super(); } //子类构造访问父类构造,可省略,系统默认
    public void methodZi(){
        //子类成员方法访问父类成员变量
        System.out.println(super.num); //10
    }
    public void method(){
        //子类成员方法访问父类成员方法
        super.method();  //输出:父类成员方法
    }
}

1.11.this关键字三种用法

  • this关键字三种用法  this关键字访问本类内容
    • 1.在本类的成员方法中,访问本类的成员变量
    • 2.在本类的成员方法中,访问本类的另一个成员方法
    • 3.在本类的构造方法中,访问本类的另一个构造方法。(与super不同)
  • 第3种用法注意事项:
    •  A.this(参数)也必须是构造方法中第一个语句,且唯一
    • B.super和this两种构造调用不能同时使用,有this无super
    • C.无参构造中的this不能无参,否则就是调用自身(成递归),有参构造中可以。
  • package demo9_extend;
    public class Fu { int num=10; }
    
    package demo9_extend;
    //this关键字三种用法  this关键字访问本类内容
    public class Zi extends Fu {
        int num=20;
        public Zi(){
            //super(); 这一行不再赠送
            this(10);//3.本类构造调用本类另一个构造,this必须是第一个语句
        }
        public Zi(int m){  System.out.println("本类含参构造方法被调用"); }
        public void showNum(){
            int num=30;
            System.out.println(num);//局部变量30
            System.out.println(this.num);//1.本类变量20
            System.out.println(super.num);//父类变量10
        }
        public void methodA(){  System.out.println("AAA"); }
        public void methodB(){
            //2.在本类的成员方法中,访问本类的另外一个成员方法
            this.methodA(); //强调该方法是本类的
            System.out.println("BBB");
        }
    }

    1.12.this与super关键字图解

  1. 首先通过类加载器将类以字节码加载到方法区,然后将main方法压住栈中执行
  2. 先在栈中声明变量Zi zi,然后在堆中开辟空间创建zi对象
  3. 然后把zi.show()方法压入栈中执行,在该方法中分别调用局部变量、this本类变量、super父类变量;
  4. 然后把zi.method()方法压住栈中执行,该方法先调用super.method()方法,即先把父类的method压入栈中执行完并销毁后继续执行zi.method方法,执行完销毁method内存,至此main方法执行完毕也被销毁。

package demo10_extend;
public class Fu {
    int num=10;
    public void method(){   System.out.println("父类方法");  }
}

package demo10_extend;
public class Zi extends Fu{
    int num=20;
    @Override
    public void method(){
        super.method(); //子类调用父类方法
        System.out.println("子类方法");
    }

    public void show(){
        int num=30;
        System.out.println(num);//30
        System.out.println(this.num);//20
        System.out.println(super.num);//10
    }
}

package demo10_extend;
//super与this关键字图解
public class Demo {
    public static void main(String[] args) {
        Zi zi = new Zi();
        zi.show();
        zi.method();
    }
}

1.13.java继承的三个特性

 

 

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值