Java之继承、封装和多态

目录

继承

继承实现

实例

方法重写

实例 

继承的构造方法的执行顺序

典例 

 super关键字

实例

final关键字

实例  

static关键字 

实例 

抽象类与抽象方法 

定义抽象类 

实例 

接口 

 接口和抽象类的区别

 接口的定义和使用

定义接口 

实例 

 接口继承

 实例

多态 

抽象类实现多态

实例

实例分析 

 接口实现多态

 实例

包的功能及介绍

包的功能

包的介绍

包的定义

包的创建

在包中创建类

类和类成员权限的设定

类的权限

类成员的权限

包的引用 

引用包中某个公有类

引用包中所有的公有类


 

 

 

 

 

 

 

 

 

 

 

 

 

继承

  • 只能存在一个父类,可以存在多个子类。
  • 父类的私有成员(访问权限为private的成员)不能被子类继承。
  • 子类继承父类的成员,同时可以定义其他的成员。
  • 允许存在多重继承,即子继承父,父继承爷。

继承实现

class 子类名称 extends 父类名称 {

        

}

实例

class Person {
	int age;
	public char gender;
	protected String name;
	private String dream;
	
	void msgPrintf(){
		System.out.println("age is " + age);
		System.out.println("gender is " + gender);
		System.out.println("name is " + name);
	}
	
	//私有方法
	private void myPrintf(){
		System.out.println("hello");
	}
	
}  //父类(只能存在一个父类,可以存在多个子类):人

//子类:老师
class Teacher extends Person {
	void teacherDream(){
		System.out.println("become teacher");
	}
}

//子类:学生
class Student extends Person {
	void studentDream(){
		System.out.println("become programmer");
	}
}

public class Text {

	public static void main(String[] args) {
		
		Teacher t1 = new Teacher();
		t1.age = 25;
		t1.gender = '女';
		t1.name = "jiangxiaoya";
		//t1.dream = "become teacher";  由于父类Person中的dream是私有成员,因此无法被子类Teacher继承
		//t1.myPrintf();  由于父类Person中的myPrintf()是私有方法,因此无法被子类Teacher继承
		t1.msgPrintf();
		t1.teacherDream();
		System.out.println();
		
		Student s1 = new Student();
		s1.age = 19;
		s1.gender = '男';
		s1.name = "haozige";
		//s1.dream = "become programmer";  由于父类Person中的dream是私有成员,因此无法被子类Student继承
		//s1.myPrintf();  由于父类Person中的myPrintf()是私有方法,因此无法被子类Teacher继承
		s1.msgPrintf();
		s1.studentDream();
		
	}
}

b768e34fe9614eb09dc8c58a0901dd27.png

方法重写

  • 当子类与父类有相同的方法时(即方法名相同、返回值类型相同、参数列表相同),此时使用创建的子类对象使用该方法时,使用的是子类的方法,即方法重写。
  • 当子类和父类的方法名相同,参数列表不同时,此时使用创建的子类对象使用该方法时,使用的是子类的方法,但属于方法重载。
  • 方法重写发生在继承类中,被重写的方法不能有更严格的权限,而方法重载发生在一个类中,对权限没有要求。
  • 当子类存在与父类相同的数据成员时,优先使用子类的数据成员。

实例 

class Person {
	int age = 99;
	public char gender;
	protected String name;
	private String dream;
	
	void msgPrintf(){
		System.out.println("age is " + age);
		System.out.println("gender is " + gender);
		System.out.println("name is " + name);
	}
}  //父类:人


//子类:学生
class Student extends Person {
	
	//方法重写,与父类的方法名相同,参数列表相同
	void msgPrintf(){
		System.out.println("my dream is become programmer");
	}	
}


class Teacher extends Person {
	
	int age = 40;  //当子类存在与父类相同的数据成员时,优先使用子类的数据成员
	
	//方法重载,与父类的方法名相同,参数列表不同
	void msgPrintf(String name){
		System.out.println(age);
		System.out.println(name);
	}
}

public class Text {

	public static void main(String[] args) {
		
		Student s1 = new Student();
		s1.msgPrintf();
		System.out.println();
		
		Teacher t1 = new Teacher();
		t1.msgPrintf("jiangxiaoya");
		
	}
}

3eb4313f4e1d4b3eb374385db3ebfd86.png

继承的构造方法的执行顺序

  • 当执行子类的构造方法时,父类以及父类的上一级结构的构造方法都会被执行,执行顺序是从最年老的到最年轻的。
  • 当子类有多个构造方法时,无论子类创建的对象使用哪个构造方法,父类以及父类的上一级结构都只会执行默认的构造方法(无参数的构造方法)。 

典例 

class Person {
	
	//构造方法
	Person() {
		System.out.println("我是人");
	}
	
	Person(String name) {
		System.out.println(name);
	}
}  //父类:人


//子类:学生
class Student extends Person {
	
	//构造方法
	Student() {
		System.out.println("我是学生");
	}
	
	Student(String name) {
		System.out.println(name);
	}
}

class Haozige extends Student {
	
	//构造方法
	Haozige() {
		System.out.println("我是浩子哥");
	}
	
	Haozige(String name) {
		System.out.println(name);
	}
}


public class Text {

	public static void main(String[] args) {
		new Haozige("haozige");  //执行匿名对象Haozige的构造方法
		
	}
}

b3de6a43641a49a28a967db60da26c75.png

 super关键字

 用途:

  • 在子类的构造方法中调用父类的构造方法。(子类创建对象时,部分数据成员使用父类的数据成员的值)
  • 当子类调用构造方法时,父类也会调用默认的构造方法,因此super关键字应用场景是调用父类有参数的构造方法
  • 在子类中调用父类的数据成员或者方法。(调用父类数据成员,当给子类的数据成员赋值之后,即使使用super关键字调用父类数据成员时,使用的也是子类成员的值)

实例

class Student  {
	int age;
	char gender;
	String name = "学生名字未知";
	String greet;
	
	Student() {
		this.greet = "I am a Student";
	}
	
	void studentPrintf(){
		System.out.println("hello teacher");
	}
}


class Haozige extends Student {
	
	public Haozige(int age,char gender,String name) {
		super();  //调用父类的构造方法
		this.age = age;
		this.gender = gender;
		this.name = name;
	}
	
	void msgPrintf(){
		
		System.out.println(super.name);  //调用父类数据成员,当给子类的数据成员赋值之后,即使使用super关键字调用父类数据成员时,使用的也是子类成员的值
		super.studentPrintf();  //调用父类方法
		
		System.out.println(age);
		System.out.println(gender);
		System.out.println(greet);
	}
	
	
}

class Jiangxiaoya extends Student {
	void msgPrintf(){
		System.out.println(super.name);  //调用父类数据成员
	}
}

public class Text {

	public static void main(String[] args) {
		
		new Haozige(19,'男',"haozige").msgPrintf();
		System.out.println();
		
		new Jiangxiaoya().msgPrintf();
	}
}

c80e82a55bc04ca8a2704c944d7a7a8c.png

final关键字

 

  • 当使用final关键字修饰数据成员时,声明该数据成员是一个常量(定义常量时应该进行初始化),常量的值不能改变。
  • 当使用final关键字修饰父类的方法时,子类继承时不能进行该方法的方法重写,但可以进行该方法的方法重载。
  • 当final关键字修饰类时,声明该类不能由其他类继承,即不能拥有孩子。

实例  

class Person  {
	int age;
	char gender;
	String name = "jiangxiaoya";
	final String greet = "I am a Person";
	
	final void msgPrintf(){
		System.out.println("hello");
	}
	
	void changeMsg(){
		name = "haozige";
		//greet = "I am Student";  数据成员常量不能被改变
	}
	
}


final class Student extends Person {
	
	//void msgPrintf(){}  由于父类的msgPrintf方法添加了final关键字,因此子类继承时不能进行方法重写,但能进行方法重载。
	void msgPrintf(String name){
		System.out.println(name);
	}
	
}

//class Jiangxiaoya extends Student{}  由于类Student添加了final关键字,因此不能生产孩子
	
	
public class Text {

	public static void main(String[] args) {
		
		new Student().msgPrintf("zhutoucai");
		
	}
}

static关键字 

  • static修饰数据成员时称为静态成员,static修饰方法时称为静态方法,类的静态成员和静态方法不需要创建对象就能使用。
  • 静态方法只可以使用静态成员和调用静态方法。
  • 如果父类有静态方法,那么子类不能进行该方法的方法重写,但可以进行方法重载,或者使用相同的方法名也定义为静态方法。

实例 

class Student  {
	static int age;  
	char gender;
	String name;

	static void initAge(){
		age = 99;  //如果age不是静态成员,则会报错,静态方法只可以使用静态成员和调用静态方法
	}
	
	void initName(){
		name = "student";
	}
	
}


class Haozige extends Student {
	
	//不能进行方法重写,但可以对父类的静态方法进行方法重载
	void initAge(int age){
		System.out.println(age);
	}
	
}


class Jiangxiaoya extends Student {
	
	//使用与父类相同的方法名也定义为静态方法,不知道是不是属于方法重写
	static void initAge(){
		age = 19;
		System.out.println(age);
	}
	
}
	
	
public class Text {

	public static void main(String[] args) {
		
		new Haozige().initAge(21);
		System.out.println();
		
		Jiangxiaoya.initAge();  //调用静态方法时,可以不用创建对象
		
	}
}

抽象类与抽象方法 

  • 使用abstract关键字定义抽象类。
  • 抽象类是一个模板父类,让继承的子类实现模板父类的抽象方法,因此抽象类不能使用new关键字创建对象,只能被其他类继承。
  • 抽象类里面允许存在普通方法和数据成员和构造方法,但必须存在一个或一个以上的抽象方法,即主体内容都是抽象方法。
  • 抽象类被子类继承后,子类必须对抽象方法进行方法重写(即抽象方法的具体化)。
  • 继承抽象类的子类可以在构造方法中使用super关键字调用抽象类的构造方法,或者使用super关键字调用普通方法。

定义抽象类 

abstract class 类名称 {

        数据成员;

        普通方法{

        }

        修饰符 abstract 抽象方法;

}

实例 

//使用abstract关键字定义抽象类
abstract class Student {
	//数据成员
	int age;
	char gender;
	String name;
	String greet;
	
	//构造方法1
	Student() {
		this.greet = "父类构造方法1";
	}
	
	//构造方法2
	Student(int age) {
		this.greet = "父类构造方法2";
	}
	
	//普通方法
	void myPrintf(){
		System.out.println("hello");
	}
	
	//抽象方法
	abstract void msgPrintf();
	
	
}

//继承抽象类
class Haozige extends Student {

	//子类的构造方法
	Haozige(int age,char gender,String name){
		super(99);  //使用super关键字调用父类的构造方法2,注释掉该行时,会调用父类的构造方法1
		this.age = age;
		this.gender = gender;
		this.name = name;
	}
	
	//实现抽象方法
	public void msgPrintf() {
		System.out.println(name);
		System.out.println(age);
		System.out.println(gender);
		System.out.println(greet);
		
		super.myPrintf();  //调用父类的普通方法
	}
	
	
}


public class Text {

	public static void main(String[] args) {	
		Haozige h1 = new Haozige(20, '男', "haozige");
		h1.msgPrintf();
		
	}
}

接口 

 接口和抽象类的区别

  • 接口类似于抽象类,只提供方法的定义,让使用接口的类实现接口定义的方法
  • 一个类只能继承一个父类,而一个类能实现多个接口  ,处于不同层次的类可以实现同一个接口
  • 抽象类有数据成员、常量、普通方法和抽象方法,而接口只有常量和抽象方法
  • 接口内的方法在编译时,自动变成public和abstract类型,即变成公有抽象方法,而接口内的数据成员在编译时,自动变成public和final类型,即变成公有常量。

 接口的定义和使用

  • 使用interface关键字定义接口,类使用implements实现接口
  • 接口的数据成员必须赋值,编译时会变成常量
  • 不能将接口方法声明为私有接口方法

定义接口 

interface 接口名称 {

        修饰符 数据成员
        修饰符 普通方法;

}

实例 

//定义接口1
interface Haozige {
	int age = 20;  //接口内定义的数据成员必须进行初始化,因为他们编译后会变成公有常量
	String name = "haozige";
	
	//接口方法
	void haozigePrintf();  //接口方法在编译时会变成公有抽象方法
	
}

//定义接口2
interface Jiangxiaoya {
	int age = 19;  
	String name = "jiangxiaoya";
	
	//接口方法
	void jiangxiaoyaPrintf();  
	
}

//实现接口的类
class Teacher implements Haozige{
	
	//实现接口方法
	public void haozigePrintf(){
		System.out.println(age);  //使用接口的常量
		System.out.println(name);  
		
	}
}

//一个类可以同时实现多个接口
class Student implements Haozige,Jiangxiaoya {
	
	//实现Haozige接口的接口方法
	public void haozigePrintf(){
		System.out.println(Haozige.age);  //使用接口的常量,如果实现了多个接口,接口的常量名重合时,使用接口名来区分常量
		System.out.println(Haozige.name);
	}
	
	//实现Jiangxiaoya接口的接口方法
	public void jiangxiaoyaPrintf(){
		System.out.println(Jiangxiaoya.age);
		System.out.println(Jiangxiaoya.name);  
	}
	
}

public class Text {

	public static void main(String[] args) {	
		
		new Teacher().haozigePrintf();
		System.out.println();
		new Student().haozigePrintf();
		System.out.println();
		new Student().jiangxiaoyaPrintf();
	}
}

 接口继承

  • 接口也可以像类一样继承,即子接口使用extends关键字继承父接口
  • 实现子接口的类不仅要实现自子接口的接口方法,还要实现父接口或更上层接口的接口方法

 实例

//定义接口Person
interface Person {
	
	void personPrintf();

}

//定义子接口继承父接口Person
interface Student extends Person {
	
	void studentPrintf();

}

//定义一个类实现子接口
class Haozige implements Student {
	
	//实现子接口接口方法
	public void studentPrintf(){
		System.out.println("我是子接口");
	}

	//如果父接口或者更上层接口的接口方法没有实现就会报错
	public void personPrintf() {
		System.out.println("我是父接口");
		
	}

}

public class Text {

	public static void main(String[] args) {	
		
		new Haozige().studentPrintf();
		new Haozige().personPrintf();
	}
}

多态 

多态能让不同对象执行相同的方法却能实现不同的结果

抽象类实现多态

抽象类对象能够引用子类的对象,当引用成功后,能使用子类对象的数据成员和方法。

实例

import java.util.Scanner;

//定义一个抽象类
abstract class Dayindian {
	String dName = "谢谢惠顾,你购买的打印机是";
	abstract void myPrintf();//
}

class HeibaiDayinji extends Dayindian {
	String hName = "黑色打印机";
	void myPrintf() {	
		System.out.println("黑白打印机");
		System.out.println(hName);
	} 
}

class CaisheDayinji extends Dayindian {
	String cName = "彩色打印机";
	void myPrintf() {
		System.out.println("彩色打印机");
		System.out.println(cName);
	}
}

public class Text {
	
	public static void main(String[] args) {	
		
		//让一个抽象类对象,根据不同的程序逻辑引用不同的子对象,来使用子对象的方法
		
		Dayindian d;//声明抽象类对象
		HeibaiDayinji h = new HeibaiDayinji();//创建黑白打印机对象
		CaisheDayinji c = new CaisheDayinji();//创建彩色打印机对象
	
		Scanner sc = new Scanner(System.in);  //使用输入类
		int tmp;
		while(true){
			System.out.println("欢迎光临");
			System.out.println("请选择打印机:1.黑白打印机    2.彩色打印机    3.不买了");
			
			tmp = sc.nextInt();
			
			if(tmp == 1){
				d = h;  //让抽象类对象引用黑白打印机对象
			}else if(tmp == 2){
				d = c;  //让抽象类对象引用彩色打印机对象
			}else{
				break;
			}
		
		System.out.println(d.dName);  //使用抽象类的数据成员
		d.myPrintf();  //当对象类引用子类对象成功后,使用抽象类方法时,将会调用子类方法
		
		}
		
	}
}

实例分析 

没引用对象前的内存分配

Dayindian d;        //声明抽象类对象
HeibaiDayinji h = new HeibaiDayinji();        //创建黑白打印机对象
CaisheDayinji c = new CaisheDayinji();        //创建彩色打印机对象 

60f6b63c2be34b3693bf166daa30eb70.png

 d = h;        //让抽象类对象引用黑白打印机对象

c47d09f91e4e49409da7a6e9b22dffac.png

d = c;        //让抽象类对象引用彩色打印机对象 

602df8cda3364fb0b21b1b58a788d172.png

 接口实现多态

当某个子类已经继承一个父亲时,该子类无法通过继承一个抽象类来完成多态(即该子类同时只能拥有一个父亲),因此只能选择用接口完成多态。

 实例

接口实现多态跟抽象类实现多态大同小异

import java.util.Scanner;

//定义一个接口
interface Dayindian {
	String dName = "谢谢惠顾,你购买的打印机是";
	void myPrintf();
}

class HeibaiDayinji implements Dayindian {
	String hName = "黑色打印机";
	public void myPrintf() {	
		System.out.println("黑白打印机");
		System.out.println(hName);
	} 
}

class CaisheDayinji implements Dayindian {
	String cName = "彩色打印机";
	public void myPrintf() {
		System.out.println("彩色打印机");
		System.out.println(cName);
	}
}

public class Text {
	
	public static void main(String[] args) {	
		
		Dayindian d;//声明接口对象
		HeibaiDayinji h;  //声明黑白打印机对象
		CaisheDayinji c;  //声明彩色打印机对象
	
		Scanner sc = new Scanner(System.in);  //使用输入类
		int tmp;
		while(true){
			System.out.println("欢迎光临");
			System.out.println("请选择打印机:1.黑白打印机    2.彩色打印机    3.不买了");
			
			tmp = sc.nextInt();
			
			if(tmp == 1){
				//h = new HeibaiDayinji(); 
				//d = h;
				d = new HeibaiDayinji();  //让接口对象引用黑白打印机对象
			}else if(tmp == 2){
				//c = new CaisheDayinji();
				//d = c;
				d = new CaisheDayinji();  //让接口对象引用彩色打印机对象
			}else{
				break;
			}
		
		System.out.println(Dayindian.dName);  //使用接口的数据成员
		d.myPrintf();  
		
		}
		
	}
}

包的功能及介绍

包的功能

  • 解决命名冲突的问题,同一个包中的类名不能相同
  • 将同一个类型的类集中在一个包中,让项目整体架构更清晰

包的介绍

  • 一个包中能存在多个.java文件。
  • 一个.java文件中只能存在一个公有类,该公有类名字与.java文件的名字必须一样,可以存在多个默认类。

97465af3e85743469ef705d1e54760de.png

包的定义

包的创建

在src目录下->New->Package

d7e39c1c19de46b4b3acd4bce66ce09a.png

f289804448f84e459937c87c336e8933.png

在包中创建类

在包目录下->New->Class

5d98eabea7864baebc0a71598c86a8e1.png

dc983a75895141a9831428b51eca9169.png  

类和类成员权限的设定

类的权限

类的权限只有public和默认,即类按权限分为公有类和默认类

  • 公有类:能在同一个包中或者不同的包中使用该公有类。
  • 默认类:只能在同一个包中使用该默认类。

类成员的权限

df9b216c08164589a09b8ee6fd938d1e.png

  • private(私有成员):只有同一个类可以使用
  • 默认(默认成员):同一个包中的类可以使用
  • protected(保护成员):同一个包中的类都可以使用,以及不同包中的非子类可以使用
  • public(公有成员):任何包中的类都可以使用

包的引用 

引用包中某个公有类

import 包名称.类名

引用包中所有的公有类

import 包名称.* 

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值