第十三章_类的继承

第十三章 类的继承


提纲

  • 13.1 概念
  • 13.2 Java中的继承
    • 13.2.1 父类和子类
    • 13.2.2 定义继承的语法
    • 13.2.3 举例
    • 13.2.4 继承的好处
    • 13.4.5 继承需要注意的地方
  • 13.3 super关键字
    • 13.3.1 super关键字的作用
    • 13.3.2 如何使用构造函数给父类传参
    • 13.3.3 总结
  • 13.4 方法的重写
    • 13.4.1 什么是方法重写
    • 13.4.2 重写的特点
    • 13.4.3 重写举例
  • 13.5 继承与访问权限的关系
  • 13.3 作业

13.1 概念

  1. 继承的含义:继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。

  2. 生活中的继承:

     				动物
     	食草动物				肉食动物
     兔子	牛	羊....		老虎	狮子	猎豹  
    

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
解释:兔子、牛、羊属于食草动物类,老虎、狮子、猎豹于食肉动物类。食草动物和食肉动物又是属于动物类。父类更通用,子类更具体。虽然食草动物和食肉动物都是属于动物,但是两者的属性和行为上有差别,所以子类会具有父类的一般特性也会具有自身的特性。
3. 为什么使用继承
- 从已有的类派生出新的类,称为继承。
- 在不同的类中也可能会有共同的特征和动作,可以把这些共同的特征和动作放在一个类中,让其它类共享。 因此可以定义一个通用类,然后将其扩展为其它多个特定类,这些特定类继承通用类中的特征和动作。
- 继承是 Java 中实现软件重用的重要手段,避免重复,易于维护,易于理解。


13.2 Java中如何继承

  • 13.2.1 父类和子类:

    • 如果类 B 从类 A 派生,或者说类 B 扩展自类 A,或者说类 B 继承类 A
    • 则称类 A 为"父类",又称超类、基类
    • 称类 B 为"子类",又叫派生类、次类、扩展类
  • 13.2.2 定义继承的语法:修饰符 class 子类名 extends 父类名{}

  • 13.2.3 举例:

      //定义一个动物类Animal
      public class Animal {
      	
    
      }
      //定义一个老虎类Tiger,因为老虎是属于动物的,所以老虎是子类,动物是父类
    

    public class Tiger extends Animal{

      }
      //还可以定义多个子类
    

    public class Rabbit extends Animal{

      }
      ...
    
  • 13.2.4 继承的好处:现有大儿子和小儿子两个类,类中有属性姓名、性别和年龄,类中有方法吃,内容输出为:XXX正在吃,睡,内容输出为:XXX正在睡,自我介绍,内容为大家好!我是XXX,性别是XXX,今年XX岁了。

      //非继承状态下有两个类,小儿子和大儿子
      //大儿子类
      public class BigSon {
      	String name;
      	String sex;
      	int age;
      	public void eat(){ 
              System.out.println(name+"正在吃"); 
          }
          public void sleep(){
              System.out.println(name+"正在睡");
          }
          public void introduction() { 
              System.out.println("大家好!我是:"+ name + ",性别是:" + sex + ",今年"+age+"岁"); 
          }
      }
      //小儿子类
      public class SmallSon {
      	String name;
      	String sex;
      	int age;
      	public void eat(){ 
              System.out.println(name+"正在吃"); 
          }
          public void sleep(){
              System.out.println(name+"正在睡");
          }
          public void introduction() { 
              System.out.println("大家好!我是:"+ name + ",性别是:" + sex + ",今年"+age+"岁"); 
          } 
      }
    

    结论:功能虽然已经实现,但是代码量大且臃肿,两个类中是完全一模一样的代码,如果出现三儿子、四儿子…那代码量可想而知。

      //经继承优化之后的代码
      //首先,定义一个父亲类,因为大儿子和小儿子都是父亲的子类
      public class Father {
      	String name;
      	String sex;
      	int age;
      	public void eat(){ 
              System.out.println(name+"正在吃"); 
          }
          public void sleep(){
              System.out.println(name+"正在睡");
          }
          public void introduction() { 
              System.out.println("大家好!我是:"+ name + "性别是:" + sex + ",今年"+age+"岁"); 
          }
      }
      //大儿子继承父亲
      public class BigSon extends Father{
      
      }
      //小儿子继承父亲
      public class SmallSon extends Father{
       
      }
      //创建测试类测试
      public class Test {
      	public static void main(String[] args) {
      		SmallSon ss = new SmallSon();
      		ss.name = "张三";
      		ss.age = 18;
      		ss.sex = "男";
      		ss.eat();
      		ss.sleep();
      		ss.introduction();
      		BigSon bs = new BigSon();
      		bs.name = "李四";
      		bs.age = 14;
      		bs.sex = "女";
      		bs.eat();
      		bs.sleep();
      		bs.introduction();
      	}
      }
      //执行结果
      张三正在吃
      张三正在睡
      大家好!我是:张三性别是:男,今年18岁
      李四正在吃
      李四正在睡
      大家好!我是:李四性别是:女,今年14岁
    

    结论:使用继承之后,可以发现这个Father类就可以作为一个父类,然后小儿子类和大儿子类继承这个类之后,就具有父类当中的属性和方法,子类就不会存在重复的代码,维护性也提高,代码也更加简洁,提高代码的复用性(复用性主要是可以多次使用,不用再多次写同样的代码)。

  • 13.4.5 继承需要注意的地方

    1. 在Java中,类的继承是单一继承,也就是说,一个子类只能拥有一个父类,所以 extends 只能继承一个类。

    2. 子类不是父类的子集,子类一般比父类包含更多的数据域和方法。

    3. 父类中的 private 数据域在子类中是不可见的,因此在子类中不能直接使用它们。

       //继续4中的例子
       //在Father中加入私有属性小三和私有方法按摩
       private otherWomen = "小莉";
       private void massage(){
       	System.out.println("去按摩");
       }
       //在子类中,无法调用并使用该属性,除非父类中提供有getter和setter方法才可以对其进行调用和修改
       //也无法调用该massage方法
      
    4. 如果要继承,父类与子类之间就必须存在继承关系。


13.3 super关键字

  • 13.3.1 super关键字的作用

    • 调用父类构造方法语法:super();或者super(参数列表);如果父类没有空的构造方法,子类一定要重写父类的构造方法。
    • 调用父类的成员变量的语法:super.变量名
    • 调用父类的方法语法:super.方法名(参数列表);
  • 13.3.2 如何使用构造函数给父类传参。

      //这里只写添加的代码。
      //首先,父类中编写传递参数的构造函数
      public Father(String name, String sex, int age) {
      	this.name = name;
      	this.sex = sex;
      	this.age = age;
      }
      //大儿子类中
      String name;//大儿子自己的name属性
      public BigSon(String name, String sex, int age,String name) {
      	super(name, sex, age);//父亲名字
      	this.name = name;//大儿子名字
      }
      
    
      public void display(){
      	System.out.println("大儿子的名字是:"+this.name+",父亲的名字是:"+super.name);
      }
      //在Test类的main方法中
      BigSon bs = new BigSon("Father", "男", 55, "BigSon");
      bs.display();
      //执行结果
      大儿子的名字是:BigSon,父亲的名字是:Father
    
  • 13.3.3 总结

    • super 语句必须是子类构造方法的第一条语句。
    • 不能在子类中使用父类构造方法名来调用父类构造方法,必须用super()来调用。
    • 父类的构造方法不被子类继承。调用父类的构造方法的唯一途径是使用 super 关键字,如果子类中没显式调用,则编译器自动将 super(),作为子类构造方法的第一条语句,如果父类中没有空的构造方法,则子类必须使用super()给父类的构造方法传参,否则会编译错误。super();
    • 静态方法中不能使用 super 关键字。
    • 使用this和super来区分是本类的还是父类的属性与方法。

13.4 方法的重写

  • 13.4.1 什么是方法重写:

    • 如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写 (Overriding)。在Java中,子类可继承父类中的方法,而不需要重新编写相同的方法。
    • 但有时子类并不想原封不动地继承父类的方法,而是想作一定的修改,这就需要采用方法的重写。
    • 方法重写又称方法覆盖。
  • 13.4.2 重写的特点:

    1. 若子类中的方法与父类中的某一方法具有相同的方法名、返回类型和参数表,则新方法将覆盖原有的方法。如需父类中原有的方法,可使用super关键字,该关键字引用了当前类的父类。
    2. 重写的方法中子类函数的访问修饰权限不能少于父类的。
  • 13.4.3 重写举例:

      //汽车类
      public class Car {
      	//开车的方法
      	public void drive(){
      		System.out.println("开汽车");
      	}
      }
      //本田车类属于汽车类
      public class Honda extends Car{
      	@Override//Override覆盖、重写的意思
      	public void drive() {
      		//super.drive();//调用父类的开车方法
      		System.out.println("开本田牌汽车");
      	}
      }
      //宝马车类属于汽车类
      public class BMW extends Car{
      	@Override
      	public void drive() {
      		System.out.println("开宝马牌汽车");
      	}
      }
      //保时捷车类属于汽车类
      public class Porsche extends Car{
      	@Override
      	public void drive() {
      		System.out.println("开保时捷牌汽车");
      	}
      }
      //不管什么车子都必须由人来开,所以定义一个人类,并且定义一个开车的方法
      public class Person {
      	//定义开车方法并不知道开的是什么车,所以定义他们所有车的父类
      	public void drive(Car car){
      		car.drive();
      	}
      }
      //定义一个测试类
      public class Test {
      	public static void main(String[] args) {
      		Person person = new Person();
      		//直接传入子类对象,得到对应的结果
      		person.drive(new BMW());
      		person.drive(new Honda());
      	}
      }
    

13.5 继承与访问权限的关系

//在上述例子中的Father加入两个属性
public String face = "超级帅";//相貌
protected double money = 500000;//钱
//加入受保护的方法
protected void run() {
	System.out.println("在跑步");
}
//加入默认的方法
void makeMoney(){
	System.out.println("老爸赚钱很厉害");
}
//在com.zxjy.test包中定义一个三儿子
public class ThreeSon extends Father{
	public void display(){
		//在这里,调用的属性只有face和money,调用的方法为eat()、sleep()、introduction()、run(),无法调用私有方法和默认方法
		System.out.println("长的有老爸那么:"+super.face+",拿着老爸的钱:"+super.money);
	}
}
//Test类测试
ThreeSon ts = new ThreeSon();
ts.display();
ts.run();
//执行结果
长的有老爸那么:超级帅,拿着老爸的钱:500000.0
在跑步

三、作业

  • 请用继承的思想,改写下面的类:
    1. 现在有笛子类与钢琴类如下:问:请用继承的思想,更改下面的类。

       /**
        * 乐器类
        */
       Public abstract class Instrument(){
       	
       }
       /**
        * 钢琴类
        */
       public class Piano  {
       	public void play() {
       		System.out.println("钢琴是弹的");
       	}
       }
       /**
        * 笛子类
        */
       public class Flute {
       	public void play() {
       		System.out.println("笛子是吹的");
       	}
       }
      
    2. 现在有小学生类与大学生类:问:请用继承的思想,改写下面的类。要求性别属性在构造函数中初始化。

       /**
      

      public class student{

      ​ public String sex;

      ​ public student(String sex){

      ​ this.sex=sex;

      ​ }

      }

        * 小学生
        */
       public class SmallStudent {
       	public String sex;
       	
      
       	public void study() {
       		System.out.println("学习小学课本");
       	}
       	
       	public String getSex() {
       		return this.sex;
       	}
       }
       /**
        * 大学生类
        */
           public class BigStudent {
               public String sex;
       
               public void study() {
                   System.out.println("学习大学课本");
               }
       
               public String getSex() {
                   return this.sex;
               }
           }
      
    3. 现在有白猪类和黑猪类如下:问:请用继承的思想,改写下面的类。要求性别属性在构造函数中初始化。

       /**
        * 黑猪类
        */
       public class BlackPig {
       	private String color;
       	
      
       	public BlackPig() {
       		this.color = "黑";
       	}
       	
       	public String getColor() {
       		return this.color;
       	}
       	
       	public int attack() {
       		return 50;
       	}
       }
       /**
        * 白猪类
        */
       public class WritePig {
       	private String color;
       	
       	public WritePig() {
       		this.color = "白";
       	}
       	
       	public String getColor() {
       		return this.color;
       	}
       	
       	public int attack() {
       		return 100;
       	}
       }
      
  • 看代码,说出结果和原因:
    1. 第一题:

       import java.util.Arrays;
       public class A {
       	public int i;
       	public float j;
       	public String s;
       	public int[] arr;
       	public char c;
       	
      
       	public static void main(String[] args) {
       		A a = new A();
       		System.out.println(a.i);
       		System.out.println(a.j);
       		System.out.println(a.s);
       		System.out.println(a.c);
       		
       		//Arrays.toString方法用来将数组内容打印出来
       		System.out.println(Arrays.toString(a.arr));
       	}
       }
      
    2. 第二题:

       public class A {
       	public String i;
       	
      
       	public A() {
       		System.out.println(this.i);
       	}
       	
       	public static void main(String[] args) {
       		A a = new A();
       	}
       }
      
    3. 第三题:

       public class A {
       	public B b = new B();
       	
      
       	public A() {
       		System.out.println("A");
       	}
       	
       	public static void main(String[] args) {
       		A a = new A();
       	}
       }
       
       class B {
       	public B() {
       		System.out.println("B");
       	}
       }
      
    4. 第四题:

       class C {
       	public C() {
       		System.out.println("C");
       	}
       }
       
      
       class A extends C{
       	
       	public A() {
       		System.out.println("A");
       	}
       	
       	public static void main(String[] args) {
       		A a = new A();
       	}
       }
      
    5. 第五题:

       class C {
       	public C() {
       		System.out.println("C");
       	}
       }
       class B extends C{
       	public B() {
       		System.out.println("B");
       	}
       }
       class A extends B{
       	
      
       	public A() {
       		System.out.println("A");
       	}
       	
       	public static void main(String[] args) {
       		A a = new A();
       	}
       }
      
    6. 第六题:

       class C {
       	public C() {
       		System.out.println("C");
       	}
       }
       class B {
       	public B() {
       		System.out.println("B");
       	}
       }
       class A extends C{
       	public B b = new B();
       	int num=10;
       	public A() {
              num=100;
       		System.out.println("A");
       	}
       	
       	public static void main(String[] args) {
       		A a = new A();
       	}
       }
      
  • 继承作业练习:
    • 练习一:
      1. 设计一个学生类Student,其属性有name(姓名)、age(年龄)和degree(学位)。Show()方法显示信息和构造函数。由Student类派生出本科类与研究生类。
      2. 本科生类Undergraduate和研究生类Graduate,本科生类Undergraduate增加属性specialty(专业),添加方法UndergraduateShow()显示信息。
      3. 研究生类Graduate增加属性direction(研究方向)。添加GraduateShow()方法,用于输出对象的信息。
      4. 本科生类Undergraduate和研究生类Graduate定义构造函数初始化属性(要求使用super调用父类的构造函数)。
    • 练习二:
      1. 创建一个武器类Weapen,具有攻击力Power(public ),速度speed(public )字段,并实现构造方法。
      2. 创建一个Tank类,从Weapen类继承,具有私有的方向字段dir(上下左右),并用属性封装。定义攻击方法TankAttack(),打印"我是坦克,向**方向运动,速度***,攻击力***"。
      3. 创建一个子弹类Bullen,从Weapen类继承,具有私有的type字段(表示子弹类型,如:机枪子弹,步枪子弹),用属性封装。定义攻击方法BullenAttack(),打印"我是子弹***,速度***,攻击力***"。
      4. 为Tank类和Bullen类定义构造函数初始化属性(要求使用super调用父类的构造函数)。
      5. 创建一只Tank对象,调用其方法;创建一只Bullen,调用其方法。
    • 练习三:使用继承机制实现动物世界:
      1. 创建控制台应用程序
      2. 创建所有动物的基类Animal类,定义姓名(name),体重(weight)属性,并创建构造函数初始化属性,定义吃(Eat)的方法,输出“真好吃”。
      3. 创建狗类(Dog),青蛙类(Frog)继承至动物类。
      4. 为Dog添加咬人的方法,输出“惹我罗,咬死你!”;为Frog添加游泳的方法,输出“洗个澡,真凉快!”。
      5. 为狗类和青蛙类定义构造函数初始化属性(要求使用super调用父类的构造函数)。
      6. 创建一只狗对象,调用其方法;创建一只青蛙,调用其方法。
    • 练习四:
      1. 创建一个动物类:Animal:字段:name,sex~~访问修饰符均为public。Amimal:构造函数:无参,带两个参的分别为name和sex赋值

      2. 创建一个鸡类Ji继承于Animal:Ji:私有字段:chiBang,用属性封装。Ji:构造函数:带三个参的分别为name和sex和chiBang赋值,name和sex在父类赋值。Ji :JiToString()方法,用来作自我介绍,返回:我是XXX,我是XXX,我有XXX。

      3. 创建一个狗类Dog继承于Animal:Dog:私有字段:weiBa,用属性封装。Dog:构造函数:带三个参数分别为name,sex,weiBa赋值,name和sex在父类赋值。Dog: DogToString()方法,用来作自我介绍,返回:我是XXX,我是XXX,我有XXX。

      4. 在测试类Main方法内:定义二个鸡对象:

         花花,母,一对金黄色的翅膀
         草草,公,一对银黄色的翅膀
         定义二个狗对象:
         小白,公,一条金白色的尾巴
         小黄,母,一条银白色的尾巴
         生成4个对象,分别调用相应的方法。
        

,调用其方法。
- 练习四:
1. 创建一个动物类:Animal:字段:name,sex~~访问修饰符均为public。Amimal:构造函数:无参,带两个参的分别为name和sex赋值
2. 创建一个鸡类Ji继承于Animal:Ji:私有字段:chiBang,用属性封装。Ji:构造函数:带三个参的分别为name和sex和chiBang赋值,name和sex在父类赋值。Ji :JiToString()方法,用来作自我介绍,返回:我是XXX,我是XXX,我有XXX。
3. 创建一个狗类Dog继承于Animal:Dog:私有字段:weiBa,用属性封装。Dog:构造函数:带三个参数分别为name,sex,weiBa赋值,name和sex在父类赋值。Dog: DogToString()方法,用来作自我介绍,返回:我是XXX,我是XXX,我有XXX。
4. 在测试类Main方法内:定义二个鸡对象:

			花花,母,一对金黄色的翅膀
			草草,公,一对银黄色的翅膀
			定义二个狗对象:
			小白,公,一条金白色的尾巴
			小黄,母,一条银白色的尾巴
			生成4个对象,分别调用相应的方法。

  • 20
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值