封装和继承

80 阅读17分钟

初识面向对象

1. 万物皆对象

万物皆对象是指可以将自然界中的任何事物都理解为一个对象。分析其共有的特征,称之为属性;分析其共有的行为,称之为方法。

类是由属性和方法组成的。

类是对象的抽象,对象是类 的具体。

2. 创建类

/**
 * 	学生类
 * 	类的组成包括:属性和方法
 * 	属性:一组对象共同拥有的特征,称之为属性
 * 	方法:一组对象共同拥有的行为,称之为方法
 * 
 * 	属性:
 * 		姓名/年龄/学号/性别/身高/班级/体重/专业/...
 * 
 * 	行为:
 * 		学习/吃饭/睡觉/打游戏/...
 * 	
 * @author WHD
 *
 */
public class Student {
	String name;
	int age;
	String  studentNo;
	char sex;
	double height;
	String gradeName;
	double weight;
	String profession;
	public void study() {
		System.out.println("努力学习");
	}
	public void eat() {
		System.out.println("吃饭");
	}
	public void sleep() {
		System.out.println("睡觉");
	}
	public void playGame() {
		System.out.println("打游戏");
	}
}

3.创建和使用对象

public class Student {
	String name;
	int age;
	String  studentNo;
	char sex;
	double height;
	String gradeName;
	double weight;
	String profession;
	public  void study() {
		System.out.println(name + "努力学习");
	}
	public void eat() {
		System.out.println(name + "在吃饭");
	}
	public void sleep() {
		System.out.println(name + "在睡觉");
	}
	public void playGame() {
		System.out.println(name + "在打游戏");
	}
	public void printInfo() {
		System.out.println("我的名字是:" + name);
		System.out.println("我的年龄是:" + age);
		System.out.println("我的身高是:" + height);
		System.out.println("我的体重是:" + weight);
		System.out.println("我的学号是:" + studentNo);
		System.out.println("我的性别是:" + sex);
		System.out.println("我的专业是:" + profession);
		System.out.println("我的班级是:" + gradeName);
	}
	public static void main(String[] args) {
		// 1.先new对象   类名 对象名 =  new 类名();
		Student stu1 = new Student();
        
		// 2.通过对象名.属性名  对属性赋值
		stu1.name = "赵四";
		stu1.age = 18;
		stu1.height = 180.5;
		stu1.sex = '男';
		stu1.studentNo = "zz0001";
		stu1.profession = "形体艺术";
		stu1.gradeName = "三年二班";
		stu1.weight = 70;

		// 3.通过对象名.方法名 访问对象的行为 (方法)
		stu1.study();
		stu1.sleep();
		stu1.eat();
		stu1.playGame();
		
		stu1.printInfo();
		
		System.out.println("----------------------------------------");
		
		Student stu2 = new Student();
		stu2.name = "广坤";
		stu2.age = 20;
		stu2.height = 175;
		stu2.profession = "语言艺术";
		stu2.sex = '男';
		stu2.gradeName = "三年二班";
		stu2.weight = 65;
		stu2.studentNo =  "zz0002";
		
		stu2.study();
		stu2.sleep();
		stu2.playGame();
		stu2.eat();
		stu2.printInfo();
	}
}

4.实例变量

实例变量,也叫成员变量,也叫属性

描述实例变量局部变量
定义位置直接写在类中方法中
默认值默认值与数组相同没有默认值
作用范围整个类中离当前变量最近的大括号以内
命名冲突可以与局部变量重名,就近原则重合的作用范围,不能重名
存储位置全部存储在堆中,所以才有默认值基本数据类型,存在栈中;引用数据类型,名字在栈,值在堆中
生命周期随着创建对象而生效,随着对象被垃圾回收而死亡随着方法的入栈而生效,随着方法的出栈而死亡

5. 方法重载

方法重载:

1.同一个类中

2.方法名称相同,

3.参数列表不同(包括参数的个数、类型、顺序有一个不同即可称之为不同),

<访问修饰符,返回值是否相同不作为方法重载的参考条件>

这种情况,称之为方法重载

调用带有重载的方法时,需要根据传入的实参去找到与之匹配的方法。
好处:屏蔽使用差异,灵活、方便。

import java.util.Arrays;
/**
 * 	方法重载:
 * 	1.同一个类中
 * 	2.方法名称相同,
 * 	3.参数列表不同(包括参数的个数、类型、顺序有一个不同即可称之为不同),
 * 	<返回值是否相同不作为方法重载的参考条件>
 * 	这种情况,称之为方法重载
 * @author WHD
 *
 */
public class Calc {
	
//	public void add(int a,String s) {
//		
//	}
	public void add(int num,String str) {
		
	}
	public int add(String str,int num) {
		return 0;
	}
	public int add(int a,int b) {
		return a + b;
	}
	public int add(int a,int b,int c) {
		return a + b + c;
	}
	public int add(int a,int b,int c,int d) {
		return a + b + c + d;
	}
	public int add(int a,int b,int c,int d,int e) {
		return a + b + c + d + e;
	}
	public static void main(String[] args) {
		Calc calc = new Calc();
		calc.add(10, 20);
		calc.add(10, 20, 30);
		calc.add("a", 20);
	}
}

6. 构造方法

构造方法:用于创建对象的特殊方法

构造方法语法:访问修饰符(public) + 类名(形参列表){}

普通方法语法:访问修饰符(public) + 返回值类型 + 方法名(形参列表){}

无参构造,JVM默认提供。如果书写了有参构造,那么无参构造将会被覆盖,想要使用,手动书写。

构造方法重载规则与方法重载一致,只有一条要求,参数列表不同。

/**
 * 	名字
 * 	年龄
 * 	性别
 * 
 * 	无参构造,JVM默认提供。如果书写了有参构造,那么无参构造将会被覆盖,想要使用,手动书写。
 * 	构造方法重载规则与方法重载一致,只有一条要求,参数列表不同。
 * @author WHD
 *
 */
public class Person {
	String name;
	int age;
	String sex;
	public void printInfo() {
		System.out.println("名字是:" + name + ",年龄:" + age + ",性别是:" + sex);
	}
	public Person(String n,int a,String s) {
		System.out.println("全参构造方法1");
		sex = s;
		age = a;
		name = n;
	}
	public Person(int a,String s,String n) {
		System.out.println("全参构造方法2");
		sex = s;
		age = a;
		name = n;
	}
	public Person() {}
	public static void main(String[] args) {
		Person p1 = new Person();
		p1.name = "赵四";
		p1.age = 20;
		p1.sex = "男";
		
		p1.printInfo();
		System.out.println("--------------------------");
		Person p2 = new Person("大拿", 20,"男");
		p2.printInfo();
		
		System.out.println("--------------------------");
		Person p3 = new Person(20, "男", "小宝");
		p3.printInfo();
	}
}

7. this关键字

this关键字:表示当前对象

适用场景: 1.可以访问属性 2.可以访问方法 3.可以访问构造方法,必须在构造方法的第一句

/**
 * 	名字
 * 	年龄
 * 	性别
 * 
 * 	this关键字:表示当前对象
 * 	适用场景:
 * 		1.可以访问属性
 * 		2.可以访问方法
 * 		3.可以访问构造方法,必须在构造方法的第一句
 * 
 * @author WHD
 *
 */
public class Person {
	String name;
	int age;
	String sex;
	public void printName() {
		System.out.println("我的名字是:" + name);
	}
	public void printAge() {
		System.out.println("我的年龄是:" + age);
	}
	public void printInfo() {
		this.printName();
		this.printAge();
		System.out.println("性别是:" + sex);
	}
	public Person(String name) {
		this.name = name;
	}
	public Person(String name,int age) {
		this(name);
		this.age = age;
	}
	public Person(String name,int age,String sex) {
		this(name,age); // 调用本类构造 必须在构造方法的第一句
		this.sex = sex;
	}
	public Person(int a,String s,String n) {
		sex = s;
		age = a;
		name = n;
	}
	public Person() {}	
}

封装

1. 封装

解决用户不合理的给属性赋值的情况,我们可以使用封装来实现

封装的步骤:

  • 1.属性私有  属性使用private关键字修饰 表示此属性只能在本类中访问 其他任何类不能访问
  • 2.方法公开  每一个属性编写一对方法 分别用于属性的赋值(set方法) 和 取值(get方法)
    公开方法 有严格的命名规范要求
    设置值的 必须为 setName()  不需要返回值 但是需要参数
    获取值的 必须为 getName()  不需要参数  但是需要返回值

封装的优点:

便于使用者正确使用系统,防止错误修改属性
降低了构建大型系统的风险
提高程序的可重用性
降低程序之间的耦合度

/**
 * 	企鹅类
 * 
 * 	名字
 * 	健康值
 * 	爱心值
 * 
 * 	解决用户不合理的给属性赋值的情况,我们可以使用封装来实现
 * 	封装的步骤:
 * 		1.属性私有  属性使用private关键字修饰 表示此属性只能在本类中访问 其他任何类不能访问
 * 		2.方法公开  每一个属性编写一对方法 分别用于属性的赋值(set方法) 和 取值(get方法) 
 * 		公开方法 有严格的命名规范要求 
 * 		获取值的 必须为 getName()  不需要参数  但是需要返回值
 * 		设置值的 必须为 setName()  不需要返回值 但是需要参数
 * @author WHD
 *
 */
public class Penguin {
	private String name;
	public  void  setName(String name) {
		this.name = name;
	}
	public String getName() {
		return name;
	}
	private int health;
	
	public void setHealth(int health) {
		if(health >= 0 && health <= 100) {
			this.health = health;
		}else {
			System.out.println("健康值赋值不合理,将使用默认值60");
			this.health = 60;
		}
	}
	public int getHealth() {
		return health;
	}
	
	private int love;
	public void setLove(int love) {
		if(love >=0 && love <= 100) {
			this.love = love;
		}else {
			System.out.println("爱心值赋值不合理,将使用默认值60");
			this.love = 60;
		}
	}
	public int getLove() {
		return love;
	}
}
public class TestPenguin {
	public static void main(String[] args) {
		Penguin p1 = new Penguin();
		
		p1.setName("大白");
		p1.setHealth(-2000);
		p1.setLove(-2000);

		System.out.println("名字是:" + p1.getName());
		System.out.println("健康值是:" + p1.getHealth());
		System.out.println("爱心值是:" + p1.getLove());
		System.out.println("----------------------------");
		Penguin p2 = new Penguin();
		p2.setName("小黑");
		p2.setLove(88);
		p2.setHealth(95);
		System.out.println("名字是:" + p2.getName());
		System.out.println("健康值是:" + p2.getHealth());
		System.out.println("爱心值是:" + p2.getLove());
	}
}

2. 访问权限修饰符

访问修饰符.png

访问修饰符2.png

2.1 类的访问修饰符

类的访问修饰符

public:公开的访问权限 本项目任何位置 都可以访问此类

默认不写:表示只能在同一个包中访问此类

/**
 * 	类的访问修饰符
 * 	public:公开的访问权限 本项目任何位置 都可以访问此类
 * 	默认不写:表示只能在同一个包中访问此类 
 * @author WHD
 *
 */
public class A {
	public static void main(String[] args) {
		A a = new A();
		
		B b = new B();
	}
}
       class B{
	public static void main(String[] args) {
		B b = new B();
	}
}
public class TestA {
	public static void main(String[] args) {
		A a = new A();
		B b = new B();
	}
}
import com.qfedu.test3.A;

public class TestA {
	public static void main(String[] args) {
		A a = new A();
	}
}

2.2 类成员的访问修饰符

类成员(属性和方法)的访问修饰符

  • private 本类中
  • 默认不写 本包中
  • protected 本类  本包 子类
  • public 任何位置
/**
 * 	类成员(属性和方法)的访问修饰符 
 * 	private 本类中
 * 	默认不写	本包中
 * 	protected 本类  本包 子类
 * 	public 任何位置
 * 
 * @author WHD
 *
 */
public class A {
	private String field1; // 字段  属性 一个意思
			String field2;
	protected String field3;
	public String field4;
	
	private void m1() {
		System.out.println("private修饰的m1方法");
	}
	void m2() {
		System.out.println("默认修饰符修饰的m2方法");
	}
	protected void m3() {
		System.out.println("protected修饰的m3方法");
	}
	public void m4() {
		System.out.println("public修饰的m4方法");
	}
	public static void main(String[] args) {
		A a = new A();
		System.out.println(a.field1);
		System.out.println(a.field2);
		System.out.println(a.field3);
		System.out.println(a.field4);
		
		a.m1();
		a.m2();
		a.m3();
		a.m4();
		
	}
}
public class TestA {
	public static void main(String[] args) {
		A a = new A();
		System.out.println(a.field2);
		System.out.println(a.field3);
		System.out.println(a.field4);
		
		a.m2();
		a.m3();
		a.m4();
		
	}
}
import com.qfedu.test5.A;

public class TestA {
	public static void main(String[] args) {
		A a = new A();
		System.out.println(a.field4);
		
		a.m4();
		
	}
}

3. static关键字

3.1 修饰属性

static可以用来修饰

成员变量

静态变量,可以直接通过类名访问

static关键字修饰的属性,在内存中只有一份,可以用于数据的共享,节省内存空间,

static修饰的变量/属性,推荐使用类名.属性名访问 因为静态变量属于整个类 不属于任何对象

是被所有当前类对象共享的数据

/**
 * 	static可以用来修饰
 *	成员变量
 *	静态变量,可以直接通过类名访问
 *
 *	static关键字修饰的属性,在内存中只有一份,可以用于数据的共享,节省内存空间,
 *	static修饰的变量/属性,推荐使用类名.属性名访问 因为静态变量属于整个类 不属于任何对象
 *	是被所有当前类对象共享的数据
 *
 *	名字
 *	年龄
 *	班级
 * @author WHD
 *
 */
public class Student {
	String name;
	int age;
	static String gradeName = "三年二班";
	
	public static void main(String[] args) {
		Student stu1 = new Student();
		stu1.name = "赵四";
		stu1.age = 20;
		stu1.gradeName = "三年三班";
		
		Student stu2 = new Student();
		stu2.name = "广坤";
		stu2.age = 21;
		
		Student stu3 = new Student();
		stu3.name = "大拿";
		stu3.age = 22;
		
		Student stu4 = new Student();
		stu4.name = "刘能";
		stu4.age = 19;
		
		System.out.println(stu1.gradeName);
		System.out.println(stu2.gradeName);
		System.out.println(stu3.gradeName);
		System.out.println(stu4.gradeName);
	}
}
/**
 * 	模拟饮水机 接水
 * @author WHD
 *
 */
public class DrinkWater {
	static int capacity = 1000; 
	String name;
	
	public void getWater() {
		if(capacity > 0) {
			capacity -= 200;
			System.out.println(name + "接水200ml,剩余" + capacity + "ml");
		}else {
			System.out.println("没水了");
		}
	}
	public static void main(String[] args) {
		DrinkWater zhaosi = new DrinkWater();
		zhaosi.name = "赵四";
		zhaosi.getWater();
		
		DrinkWater dana = new DrinkWater();
		dana.name = "大拿";
		dana.getWater();
		
		DrinkWater liuneng = new DrinkWater();
		liuneng.name = "刘能";
		liuneng.getWater();
	}
}

3.2 修饰方法

静态方法,可以直接通过类名访问

public class Test1 {
	public static void m1() {
		System.out.println("静态方法m1");
	}
	
	public static void main(String[] args) {
		Test1 test1 = new Test1();
		m1();
	}
}
public class Test2 {
	public static void main(String[] args) {
		Test1.m1();
	}
}

3.3 修饰代码块

静态代码块,当Java虚拟机加载类时(类只加载一次),就会执行该代码块

类加载的时机:

1.new对象会加载类

2.访问类中的信息 会加载类 比如访问静态变量

static代码块应用场景:用于实现一些前置的,必要的操作,并且只需要执行一次。比如数据初始化

/**
 * 	静态代码块,当Java虚拟机加载类时(类只加载一次),就会执行该代码块
 * 
 * 	类加载的时机:
 * 		1.new对象会加载类
 * 		2.访问类中的信息 会加载类 比如访问静态变量
 * 
 * 	static代码块应用场景:用于实现一些前置的,必要的操作,并且只需要执行一次。比如数据初始化
 * @author WHD
 *
 */
public class Test3 {
	static int numa = 100;
	static {
		System.out.println("静态代码块1");
	}
	
	static {
		System.out.println("静态代码块2");
	}
	
	public static void main(String[] args) {
//		System.out.println(numa);
		Test3 t1 = new Test3();
		
		Test3 t2 = new Test3();
		
		Test3 t3 = new Test3();
		
	}
}

4.static关键字实现原理

方法区:方法区是SUN公司提出的一个规范,JDK8之前称之为永久代,JDK8开始称之为元数据。

静态区:是指static相关的信息存储的区域。

创建对象的过程:

1.当我们new对象,JVM会先在方法区中检查,是否此类的class文件已经被加载。

  如果没有加载,则先将class文件加载到方法区,此时静态相关的信息将初始化

  如果已经加载,则直接执行第二步

2.在堆中开辟空间,此时实例属性将有默认值

3.将栈中的引用指向堆中的空间

永久代/元数据:因为在方法区中初始化的数据是不会随着程序的执行动态的被垃圾回收的 ,所以存储的时间比较长。另外因为方法区中的数据初始化的时机比较早,所以后来称之为元数据。

4.1 代码块

JVM加载类时,加载静态代码块

如果有多个静态块,按顺序加载

每个静态代码块只会被执行一次

4.2 静态变量

类的成员变量包括

类变量(静态变量)
被static修饰的变量
在内存中只有一个拷贝
类内部,可在任何方法内直接访问静态变量
其他类中,可以直接通过类名访问

实例变量
没有被static修饰的变量
每创建一个实例,就会为实例变量分配一次内存,实例变量在内存中有多个拷贝,互不影响

4.3 静态方法

静态方法:可直接通过类名访问
静态方法中不能使用this和super
不能直接访问所属类的实例变量和实例方法
可直接访问类的静态变量和静态方法

实例方法:通过实例访问
可直接访问所属类的静态变量、静态方法、实例变量和实例方法
静态方法必须被实现

4.4 关于访问

平级与平级的互相直接访问

非静态可以直接访问静态

静态不能直接访问非静态必须先new对象

5. 练习题

模拟实现选民投票过程:一群选民进行投票,每个选民只允许投一次票,并且当投票总数达到100时,就停止投票

/**
 * 	选民类
 * @author WHD
 *
 */
public class Vote {
	static int ticketCount;
	String name;
	
	public boolean voteFor() {
		if(ticketCount < 100) {
			ticketCount++;
			System.out.println(name + "投出了一票,还剩余" + (100 - ticketCount) + "票");
			return true;
		}else {
			System.out.println("投票截止");
			return false;
		}
	}
	
	public static void main(String[] args) {
		Vote zhaosi = new Vote();
		zhaosi.name = "赵四";
		zhaosi.voteFor();
		
		Vote guangkun = new Vote();
		guangkun.name = "广坤";
		guangkun.voteFor();
		
		Vote liuneng = new Vote();
		liuneng.name = "刘能";
		liuneng.voteFor();
		
		for (int i = 1; i < 200; i++) {
			Vote v1 = new Vote();
			v1.name = i + "号选民";
			if(!v1.voteFor()) {
				break;
			}
		}
	}
}

继承

继承是Java中实现代码重用的重要手段之一。Java中只支持单根继承,即一个类只能有一个直接父类

子类与父类必须符合is-a的关系

使用extends关键字实现继承

package com.qfedu.test3;
/**
 * 	Dog类
 * 	名字
 * 	健康值
 * 	爱心值
 * 	品种
 * 
 * 	无参构造
 * 	打印信息方法
 * @author WHD
 *
 */
public class Dog extends Pet{
	private String strain;
	public String getStrain() {
		return strain;
	}
	public void setStrain(String strain) {
		this.strain = strain;
	}
	
	public Dog() {
	}	
}
package com.qfedu.test3;
public class Penguin extends Pet{
	
	private String sex;
	
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	public Penguin() {
	}	
}
package com.qfedu.test3;
/**
 * 	宠物类   父类 
 * 	父类中保留子类共有的属性和方法
 * @author WHD
 *
 */
public class Pet {
	private String name;
	private int health;
	private int love;
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getHealth() {
		return health;
	}
	public void setHealth(int health) {
		this.health = health;
	}
	public int getLove() {
		return love;
	}
	public void setLove(int love) {
		this.love = love;
	}
	public void print() {
		System.out.println("宠物的名字是:" + name + ",健康值是:" + health + ",爱心值是:" + love);
	}
}
package com.qfedu.test3;

public class TestPet {
	public static void main(String[] args) {
		Dog dog1 = new Dog();
		dog1.setName("大黄");
		dog1.setHealth(100);
		dog1.setLove(100);
		dog1.setStrain("二哈");
		
		dog1.print(); // 目前打印信息不全 缺少品种
		System.out.println("---------------------------------");
		
		Penguin p1 = new Penguin();
		p1.setName("大白");
		p1.setHealth(100);
		p1.setLove(100);
		p1.setSex("雌");
		
		p1.print();// 目前打印信息不全 缺少性别
	}
}

1.super关键字

super 关键字 :表示父类对象

可以访问父类访问权限允许的:属性,方法,构造方法

4.1 访问属性

我们可以通过 super关键字访问父类访问权限允许的属性

package com.qfedu.test4;
/**
 * 	Dog类
 * 	品种
 * 
 * 	无参构造
 * 	打印信息方法
 * @author WHD
 *
 */
public class Dog extends Pet{
	private String strain;
	public String getStrain() {
		return strain;
	}
	public void setStrain(String strain) {
		this.strain = strain;
	}
	
	public Dog() {
	}
	public Dog(String name,int health,int love,String strain) {
		this.strain = strain;
		super.name = name;
		super.health = health;
		super.love = love;
	}

}
package com.qfedu.test5;

import com.qfedu.test4.Pet;

public class Cat extends Pet{
	private String furColor;

	public String getFurColor() {
		return furColor;
	}

	public void setFurColor(String furColor) {
		this.furColor = furColor;
	}
	
	public Cat() {}
	
	public Cat(String name,int health,int love,String furColor) {
		this.furColor = furColor;
		this.name = name;
		super.health = health;
		super.love = love;
    }
}
package com.qfedu.test4;
/**
 * 	宠物类   父类 
 * 	父类中保留子类共有的属性和方法
 * @author WHD
 *
 */
public class Pet {
	protected String name;
	protected int health;
	protected int love;
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getHealth() {
		return health;
	}
	public void setHealth(int health) {
		this.health = health;
	}
	public int getLove() {
		return love;
	}
	public void setLove(int love) {
		this.love = love;
	}
}

4.2 访问方法

我们可以通过super关键字访问父类访问权限的方法

package com.qfedu.test4;
/**
 * 	宠物类   父类 
 * 	父类中保留子类共有的属性和方法
 * @author WHD
 *
 */
public class Pet {
	protected String name;
	protected int health;
	protected int love;
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getHealth() {
		return health;
	}
	public void setHealth(int health) {
		this.health = health;
	}
	public int getLove() {
		return love;
	}
	public void setLove(int love) {
		this.love = love;
	}
	
	public void print() {
		System.out.println("宠物的名字是:" + name + ",健康值是:" + health + ",爱心值是:" + love);
	}

}
package com.qfedu.test4;
/**
 * 	Dog类
 * 	品种
 * 
 * 	无参构造
 * 	打印信息方法
 * @author WHD
 *
 */
public class Dog extends Pet{
	private String strain;
	public String getStrain() {
		return strain;
	}
	public void setStrain(String strain) {
		this.strain = strain;
	}
	
	public Dog() {
	}
	
	public void printDog() {
		super.print();
		System.out.println("狗狗的品种是:" + strain);
	}
	
}
package com.qfedu.test4;
/**
 * 	企鹅类
 * 	性别
 * 
 * 	无参构造
 * 	打印信息方法
 * @author WHD
 *
 */
public class Penguin extends Pet{
	private String sex;
	
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	public Penguin() {
	}
	
	public void printPenguin() {
		super.print();
		System.out.println("企鹅的性别是:" + sex);
	}
}

4.3 访问构造方法

1.super关键字访问父类的构造方法 必须在子类构造的第一句

2.子类构造默认访问父类的无参构造方法 除非显式调用父类的有参构造方法

也就是说 子类必须访问父类的有参或者无参构造 其中一个

package com.qfedu.test6;
/**
 * 	宠物类   父类 
 * 	父类中保留子类共有的属性和方法
 * @author WHD
 *
 */
public class Pet {
	protected String name;
	protected int health;
	protected int love;
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getHealth() {
		return health;
	}
	public void setHealth(int health) {
		this.health = health;
	}
	public int getLove() {
		return love;
	}
	public void setLove(int love) {
		this.love = love;
	}

	
	public Pet() {
		System.out.println("Pet父类的无参构造执行了");
	}
	
	public Pet(String name,int health,int love) {
		System.out.println("Pet父类的有参构造方法执行了");
		this.health = health;
		this.name = name;
		this.love = love;
	}

}
package com.qfedu.test6;
/**
 * 	Dog类
 * 	品种
 * 
 * 	无参构造
 * 	打印信息方法
 * @author WHD
 *
 */
public class Dog extends Pet{
	private String strain;
	public String getStrain() {
		return strain;
	}
	public void setStrain(String strain) {
		this.strain = strain;
	}
	
	public Dog() {
		System.out.println("Dog子类的无参构造方法执行了");
	}
	
	public Dog(String name,int health,int love,String  strain) {
		super(name, health, love);
		this.strain =strain;
	}

}
package com.qfedu.test6;
/**
 * 	企鹅类
 * 	性别
 * 
 * 	无参构造
 * 	打印信息方法
 * @author WHD
 *
 */
public class Penguin extends Pet{
	private String sex;
	
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	public Penguin() {
		System.out.println("Penguin子类的无参构造方法执行 了");
	}
}
package com.qfedu.test6;
/**	
 * 	super 关键字 :表示父类对象
 * 	可以访问父类访问权限允许的:
 * 		属性:
 * 		方法:
 * 		构造方法:
 * 		1.super关键字访问父类的构造方法 必须在子类构造的第一句
 * 		2.子类构造默认访问父类的无参构造方法 除非显式调用父类的有参构造方法
 * 		也就是说 子类必须访问父类的有参或者无参构造 其中一个
 * @author WHD
 *
 */
public class TestPet {
	public static void main(String[] args) {
		Dog dog = new Dog("大黄", 100, 100, "金毛");
		
		dog.print();
		
		System.out.println("---------------------------------");
		
		Penguin p1 = new Penguin();
		
		System.out.println("---------------------------------");
		
		Dog dog1 = new Dog();

	}
}

5. 继承总结

  • super关键字

super关键字来访问父类的成员
super只能出现在子类的方法和构造方法中
super调用构造方法时,只能是第一句
super不能访问父类的private成员

  • 继承条件下的构造方法

继承条件下构造方法的调用规则
子类构造方法没有通过super显式调用父类的有参构造方法,也没通过this显式调用自身其他构造方法
系统默认调用父类的无参构造方法
子类构造方法通过super显式调用父类的有参构造方法
执行父类相应构造方法,而不执行父类无参构造方法
子类构造方法通过this显式调用自身的其他构造方法,在相应构造方法中应用以上两条规则

  • 子类继承父类哪些内容?

子类继承父类的什么?
继承public和protected修饰的属性和方法,不管子类和父类是否在同一个包里
继承默认权限修饰符修饰的属性和方法,但子类和父类必须在同一个包里