类的继承

一、封装概述

1.1 定义

  • java语言最大的特点:面向对象

  • 面向对象的特点

    • 封装
    • 继承
    • 多态
  • 为什么要封装

    • 类中定义的属性很多,在创建对象之后我们可以随意获取和设置这些属性
    • 有些属性的值符合语法定义,但是不符合生产需求和常识
    • 需要把这个属性隐藏起来,不让外部随意访问,使用private对属性进行修饰
    • 被private修饰的属性或者方法只能在类的内部访问到,外部无法访问,所以对于类外部的其他内容来讲属性变得不可见
    • 可以在这个类的内部定义一组和属性相关的方法
      • setter
        • 设置属性的值
        • 可自定义设置的规则
      • getter
        • 获取属性值
        • 可以自定义获取的规则
  • 未封装的代码

package com.qf.pri;

public class Demo01 {
	public static void main(String[] args) {
		
		Stu stu01 = new Stu();
		stu01.name = "张三";
		stu01.age = 23;
		stu01.show();
		
		Stu stu02 = new Stu();
		stu02.name = "李思思";
		// 年龄的范围符合语法,但是不符合生产需求
		stu02.age = 2444;
		stu02.show();
	}
}

class Stu{
	// 属性
	String name;
	int age;
	String gender;
	String addr;
	
	// 方法
	public void show() {
		System.out.println("我的名字是" + name + ",我今年" + age);
	}
}

  • 封装之后的代码
package com.qf.pri;

public class Demo02 {
	public static void main(String[] args) {
		Student s01 = new Student();
		s01.name = "王五";
		s01.setAge(25);
		s01.show();
	}
}

class Student{
	// 属性
	String name;
	// 私有化属性age
	private int age;
	
	public void setAge(int age) {
		this.age = age;
	}	
	
	public int getAge() {
		return this.age;
	}
	// 方法,本类中属性即使是private修饰,也可以直接使用
	public void show() {
		System.out.println("我的名字叫" + name + ",我今年" + age);
	}
}

1.2 自定义set中的规则

  • 在set方法中可以根据生产的需求,自己定义属性的设置规则
package com.qf.pri;

public class Demo03 {
	public static void main(String[] args) {
		Stus s01 = new Stus();
		s01.name = "赵柳";
		s01.setAge(26);
		s01.show();
		
		System.out.println("===============");
		
		Stus s02 = new Stus();
		s02.name = "田七";
		s02.setAge(27777);
		s02.show();
	}
}

class Stus{
	// 属性
	String name;
	// 私有化属性age
	private int age;
	
	
	public int getAge() {
		return age;
	}


	public void setAge(int age) {
		// 自定义设置参数的规则
		if (age >= 16 && age <= 40) {
			this.age = age;
		} else {
			// 错误参数的提示
			System.err.println("年龄超出范围...");
			this.age = -1;
		}
	}


	// 方法
	public void show() {
		System.out.println("我的名字叫" + name + ",我今年" + age);
	}
}

1.3 set和get方法被绕过的情况

  • 我们创建对象的时候有可能是调用的有参数的构造方法
  • 在构造方法中可以直接给属性完成赋值的操作
  • 这样就绕过了set和get中自定义的规则
  • 如果想要set和get中的规则继续生效的话,在构造方法中调用set和get方法
package com.qf.pri;

public class Demo04 {
	public static void main(String[] args) {
		Students s01 = new Students();
		s01.name = "周毅";
		s01.setAge(21);
		s01.show();
		
		System.out.println("===============");
		
		Students s02 = new Students("吴二", 22);
		s02.show();
		
		System.out.println("===============");
		
		Students s03 = new Students("正三", 2333);
		s03.show();
				
	}
}


class Students{
	// 属性
	String name;
	private int age;

	// 构造方法
	public Students() {
		super();
	}
	
	public Students(String name, int age) {
		super();
		// 构造方法可以逃过set和get方法直接给属性赋值
		this.name = name;
		// 如果想要set中的规则继续生效就在构造方法中调用set和get方法
		this.setAge(age);
	}
	
	public int getAge() {
		return age;
	}
	
	public void setAge(int age) {
		System.out.println("setAge被调用啦啦啦啦啦");
		if (age >= 16 && age <= 40) {
			this.age = age;
		}else {
			this.age = -1;
			System.err.println("年龄范围有误....");
		}
	}
	
	// 方法
	public void show() {
		System.out.println("我是" + name + ",我今年" + age);
	}
	
}

二、继承

2.1 定义

  • 生活中的继承
    • 有亲属关系的一些人从其他亲属那里获取到遗留在人世间的财、物
  • 程序中的继承
    • 子类从父类中获取父类的属性和方法

2.2 父类的抽取

  • 从多个子类中提取出相同或者相近的属性、方法,放在一个类中,形成父类
  • 子类通过关键字extends和这个类产生继承关系
  • 子类和父类需要满足一个条件
    • 子类 is a 父类

2.3 实现继承

  • 语法

class 子类 extends 父类{

​ 子类的代码

}

  • 没有继承关系的代码
package com.qf.extend;

public class Demo01 {
	public static void main(String[] args) {
		
	}
}


  • 有继承关系的代码
package com.qf.extend;

public class Demo02 {
	public static void main(String[] args) {
		Dog dog = new Dog();
		dog.eat();
		
		dog.type = "哈士奇";
		dog.eat();
		dog.lookHome();
	}
}

/**
 * 动物类
 * 	抽取了Dog、Cat、Bear几个类中公共的属性和方法
 * @author Dushine2008
 *
 */
class Animal{
	// 共有的属性
	String type;
	String name;
	int age;
	String color;
	int weight;
	int height;
	
	// 共有的方法
	public void eat() {
		System.out.println(type + "需要吃食物维持生命活动...");
	}
	
	public void sleep() {
		System.out.println(type + "需要睡觉修复细胞...");
	}
}

/**
 * Dog类
 * 	继承了Animal
 * 	获取到了Animal属性和方法
 * @author Dushine2008
 *
 */
class Dog extends Animal{
	public void lookHome() {
		System.out.println("狗子可以看家和拆家");
	}
}

/**
 * Cat类
 * 	继承了Animal的属性和方法
 * @author Dushine2008
 *
 */
class Cat extends Animal{
	public void catchMouse() {
		System.out.println("有的猫咪会抓老鼠");
	}
}

/**
 * Bear类
 * 	继承了Animal,获取Animal的属性和方法
 * @author Dushine2008
 *
 */
class Bear extends Animal{
	public void protectForest() {
		System.out.println("熊熊要保护森林");
	}
}



三、java继承的特点

3.1 单继承

  • java中的一个类只能有一个直接父类
  • 但是父类还可以拥有父类…
  • java支持单继承,可以多级继承,子类能获取到父类、祖父类中的所有属性和方法
package com.qf.extend;

public class Demo03 {
	public static void main(String[] args) {
		// CollegeStudent的对象可以调用父类,父类的父类...中的属性和方法
		CollegeStudent cs = new CollegeStudent();
	}
}

class Human{
	// 属性
	String type;
	String faceValue;
	String name;
	String gender;
	
	// 方法
	public void eat() {
		System.out.println("人需要进食维持生命活动...");
	}
	
	public void sleep() {
		System.out.println("人需要睡觉保持精力...");
	}
}

class Student extends Human{
	// 特有的属性
	String stuId;
	String className;
	
	// 特有的方法
	public void study() {
		System.out.println("学生,以学习为主的一群人...");
	}
}

class CollegeStudent extends Student{
	// 独有的特征
	String field;
	
	
	// 独有的方法
	public void postgraduate() {
		System.out.println("大学生可以选择考研...");
	}
}

3.2 父类的构造方法

  • 子类继承不到父类的构造方法
  • 但是可以使用super调用父类的构造方法

3.3 父类私有的属性和方法

  • 子类继承不到父类的私有属性和方法
  • 因为语法规定:
    • 私有修饰的属性和方法只能在本类中访问
package com.qf.extend;

public class Demo04 {
	public static void main(String[] args) {
		Stu s01 = new Stu();
	}
}

class People{
	// 属性
	String name;
	int age;
	// 对本类的描述
	private String desc = "这个是People类的描述信息";
	
	public People() {
		super();
	}

	public People(String name, int age, String desc) {
		super();
		this.name = name;
		this.age = age;
		this.desc = desc;
	}

	public void show() {
		System.out.println("我是" + name + "我今年" + age);
	}
	
	// 私有的方法:展示自己的类信息
	private void showInfo() {
		System.out.println(desc);
	}
}

class Stu extends People{
	public void getDesc() {
		System.out.println(name);
		System.out.println(age);
		// 子类无法获取父类私有的属性和方法
		//System.out.println(desc);
	}
}

四、访问修饰符

4.1 定义

  • 通过访问修饰可以限定属性、方法、类被访问的范围
  • 目前已知的修饰符有4个
    • private

    • default/package

    • protected

    • public

      4.2 图表

种类本类本包其他类其他包子类其他位置
private×××
default××
protected×
public

五、方法重写

5.1 定义

  • 子类在继承父类后可以获取父类中所有非私有的属性和普通方法
  • 但是子类可能有自己独特的功能,继承过来的方法无法满足这些需求
  • 但是子类的功能的名字还和父类一样,这样子类就可以对从父类继承过来的方法进行重写
  • 定义
    • 子类中出现类方法声明和父类中完全相同的头条
    • 方法名字一样
    • 参数列表一样
    • 返回值类型一样
    • 权限修饰符一样或者范围更大

5.2 案例

package com.qf.override;

public class Demo01 {
	public static void main(String[] args) {
		// 方法重写案例
		WeChatV1 w01 = new WeChatV1();
		w01.chat();
		
		WeChatV2 w02 = new WeChatV2();
		w02.chat();
		
		WeChatV3 w03 = new WeChatV3();
		w03.chat();
		
		WeChatV4 w04 = new WeChatV4();
		w04.chat();
	}
}

class WeChatV1{
	public void chat() {
		System.out.println("微信第一版跨时代产品上市,能通过网络发消息,发消息免费.");
	}
}

class WeChatV2 extends WeChatV1{
	@Override
	public void chat() {
		System.out.println("微信第二版隆重上市,可以通过网络发送语音消息,每人每天可免费发出200条");
	}
}

class WeChatV3 extends WeChatV2{
	@Override
	public void chat() {
		System.out.println("微信第三版隆重上市,可以通过网络发起语音通话,通话时长无限制");
	}
}

class WeChatV4 extends WeChatV3{
	@Override
	public void chat() {
		System.out.println("微信第四版隆重上市,可以通过网络发起视频通话,通话时长无限制");
	}
}

六、关键字super

6.1 定义

  • 子类继承父类之后,可以获取父类所有非私有的普通属性和方法
  • 如果发生对属性和方法的重写,子类再次使用的时候,全部是重写之后的结果
  • 如果想调用父类中的属性和方法,需要借助关键字super

6.2 super调用属性和方法

  • super.方法名(参数列表)
    • 调用父类的方法
  • super.属性名
    • 调用父类的属性
package com.qf.override;

public class Demo02 {
	public static void main(String[] args) {
		F f = new F();
		// f.printShape();
		
		S s = new S();
		s.printShape();
		
		s.printStr();
	}
}

class F{
	
	String str = "父类中的属性str";
	
	public void printShape() {
		for (int i = 1; i < 10; i++) {
			for (int j = 1; j <= i; j++) {
				System.out.print(j + "*" + i + "=" + j*i + "\t");
			}
			System.out.println();
		}
	}
}

class S extends F{
	
	String str = "子类中的str";
	
	@Override
	public void printShape() {
		// 明确调用父类中的printShape方法
		super.printShape();
		System.out.println("==========================================================================");
	}
	
	public void printStr() {
		// 子类的str覆盖了父类继承过来的str,输出的是子类自己的
		System.out.println(str);
		
		// 如果想调用父类的str,需要使用super关键字
		System.out.println(super.str);
	}
}

6.3 super调用父类的构造方法

  • super(参数列表)
    • 调用父类的构造方法
package com.qf.override;

public class Demo03 {
	public static void main(String[] args) {
		Animal a01 = new Animal("藏獒", "狗哥", 3, "雄性");
		a01.show();
		
		Dog dog = new Dog("吉娃娃", "狗弟", 3, "雄性");
		dog.show();
	}
}

class Animal{
	// 属性
	String type;
	String name;
	int age;
	String gender;
	
	public Animal() {
		super();
	}

	public Animal(String type, String name, int age, String gender) {
		super();
		this.type = type;
		this.name = name;
		this.age = age;
		this.gender = gender;
	}

	// 方法
	public void show() {
		System.out.println("Animal [type=" + type + ", name=" + name + ", age=" + age + ", gender=" + gender + "]");
	}
	
}


class Dog extends Animal{
	public Dog() {
		super();
	}

	public Dog(String type, String name, int age, String gender) {
		// 调用父类有参数的构造方法
		super(type, name, age, gender);
	}
}

6.4 this和super

  • 调用属性
    • this.属性
      • 调用子类对自己的属性
    • super.属性
      • 调用父类的属性
  • 调用方法
    • this.方法名(参数列表)
      • 调用子类自己的方法
    • super.方法名(参数列表)
      • 调用父类的方法
  • 调用构造方法
    • this(参数列表)
      • 调用子类自己的构造方法
    • super(参数列表)
      • 调用父类的构造方法
    • 注意
      • 在调用构造方法的时候,this和super不能同时存在
      • 子类的构造方法中会默认调用父类空参的构造方法
      • 若父类只有有参构造方法,子类调用父类构造方法必须在子类构造方法的第一行写,用super(参数)的格式调用,否则报错
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值