重写、final关键字、抽象类、接口、多态、模板模式 Java第七天

本文深入解析Java中的重写(Override)概念,包括如何重写方法、属性及类,探讨final关键字的作用,以及抽象类和接口的使用。同时,文章详细阐述了多态的概念,包括继承多态和接口的多态,以及模板模式的设计原则。

重写(Override)

  定义:当子类继承父类时,子类的成员方法和父类的成员方法相同,但方法体不同,这种子类的成员方法将父类的成员方法覆盖的写法叫重写。
  判断依据:访问限定修饰符返回值类型成员方法名参数列表
 重写与重载的区别:
  重写(override):在父子类的继承中相同的方法,唯一不同的是方法体一般是父类的成员方法满足不了之类的需求才会重写
  重载(overload):在同一个类中,有相同的成员方法名,但是参数列表的数据类型或个数不同,这样的两个成员方法就是重载,重载可以提高代码的可读性,节省类中的命名资源。

class Father{
	String name = "李四";
	
	public void print() {
		System.out.println("父类方法被调用!");
	}
}

class Son extends Father{
	//这里就是重写
	public void print() {
		System.out.println(super.name + "重写方法成功!");
		System.out.println("子类方法被调用!");
	}
	
}

public class Test{
	public static void main(String[] args) {
		
		Son son = new Son();
		son.print();
	}
}

final关键字

 对成员方法

  被final关键字修饰的成员方法不能被重写。
  语法:

访问限定修饰符 final 返回值类型 成员方法名 (参数列表){
	方法体;
}

错误示范:
  下方父类成员方法由于被final修饰了,
所以子类无法重写父类的成员方法,并且代码运行后会报错!

class Father{
	String name = "李四";
	//父类成员方法被final所修饰
	public final void print() {
		System.out.println("父类方法被调用!");
	}
}

class Son extends Father{
	//这个方法将不能被重写
	public void print() {
		System.out.println(super.name + "重写方法成功!");
		System.out.println("子类方法被调用!");
	}
	
}

public class Test{
	public static void main(String[] args) {
		
		Son son = new Son();
		son.print();
	}
}

 对属性

  被final修饰的成员变量,其值不可被修改,常被用来定义常量。
  语法:

//		static可省略不写				也可以不用赋值
访问限定修饰符 static final 数据类型 成员变量名 =;

public static final int PI;
public static final int PI = 3.14;

  被final修饰的成员变量名一般采用大写,多个单词使用下划线分隔,例:XXX_YYY_ZZZ。这种常量多定义在接口中。

 对类

  被final修饰的类将不可被继承。
语法:

final class 类名{
	成员变量;
	成员方法;
}

抽象类(abstract)

 对方法

  定义:当多个具体的实体类存在着共同的成员方法,但有不同的表现,其中当子类在继承父类时,子类的成员方法具体实现不同,但是能确定子类都有这种成员方法,这种成员方法称为抽象方法。
  如果一个类中存在一个抽象方法,那么这个类一定是抽象类,这个类必须要使用 abstract 来进行修饰。
  抽象方法没有方法体。
  语法:

//返回值类型可为void   参数列表可有可无
public abstract 返回值类型 成员方法名(参数列表);

public abstract void Example();

 对类

  抽象类除了不能实例化对象之外,类的其它功能依然存在,成员变量、成员方法和构造方法的访问方式和普通类一样。
  语法:

abstract class 类名{
	成员变量;
	成员方法;
}

  注意:
 ①抽象类也可以继承抽象类,这样就可以不用实现父抽象类的抽象方法。
 ②抽象类中可以没有抽象方法,但有抽象方法的类一定是抽象类。
 ③抽象类不能直接被创建对象,需要被子类继承才能使用子类创建对象(创建子类对象)。
 ④继承抽象类的非抽象类中必须实现抽象类中的所有抽象方法。
 ⑤继承抽象类A抽象类B可以不用实现抽象类A中的抽象方法,但抽象类B不能直接创建其对象。
 ⑥抽象类的抽象方法中不能与privatefinalstatic共存 。

//定义一个抽象学生类
abstract class Student{
	//学生有成员变量,姓名
	String name;
	//学生都有学习这个成员方法
	public abstract void study();
}

class StudentA extends Student{
//非抽象学生A类继承了抽象学生类,所以要实现学习这个成员方法
	@Override
	public void study() {
		System.out.println("学生"+ name +"在听课");	
	}
}

//非抽象学生B类继承了抽象学生类,所以要实现学习这个成员方法
class StudentB extends Student{
	@Override
	public void study() {
		System.out.println("学生"+ name +"边听课,边记笔记");	
	}
}

public class Test{
	public static void main(String[] args) {
		StudentA studentA = new StudentA();
		studentA.name = "A";
		studentA.study();
		
		StudentB studentB = new StudentB();
		studentB.name = "B";
		studentB.study();	
	}
}

输出结果:
学生A在听课
学生B边听课,边记笔记

  上述代码中虽然学生A和学生B都是学生,也都有study这个成员方法,但学生A在学习时只是在听课记笔记,而学生B在学习时变听课变记笔记。这就是多个具体类存在共同成员方法,但有不同的表现。

接口(interface)

  定义:如果一个抽象类中所有的方法都是抽象方法,那么可以把这个类定义定义成接口。
  作用:
 1.接口定义的是一种标准,可以使代分层开发、分模块开发。
 2.使用接口可以降低代码耦合度,提高代码的可拓展性和可维护性。
 3.接口改进了单继承的局限。

  接口是对成员方法的抽象(不存在成员变量)。 类是对成员方法和成员属性的抽象。
  接口中可以省略abstract,默认是抽象的。
  接口不能直接被实例化,需要有类来实现接口。

接口定义语法:

interface 接口名{
	抽象方法;
}

接口实现类定义语法:
class 类名 implements 接口名1,接口名2,...{
	实现接口的方法;
}

  注意:
 ①接口中的抽象方法不能和privatestaticfinal共存。
 ②接口实现类必须实现接口中的所有方法。
 ③在接口中可以定义成员变量。访问方法:
1.通过接口的实现类的对象访问。
2.通过接口名访问(推荐)。
 ④接口中成员变量的值不可修改,并作为常量使用,默认使用public final static修饰。
 ⑤接口可以继承接口,支持多继承(jdk1.7特性)和多级继承。

通过接口名访问语法:
接口名.常量名;

接口多继承语法:
interface C extends A,B{
	常量;
	抽象方法;
}

接口多实现语法:
class C implements A,B{
	常量;
	实现抽象方法;
}

//定义接口A
interface A{
//	定义常量PI
	public final static double PI = 3.14;
//	定义抽象方法print
	public void print();
}

//定义接口B
interface B{
//	定义抽象方法print1
	public void print1();
}
//定义接口D并多继承接口A、接口B
interface D extends A,B{
//	定义常量P,并使用“接口名.常量名”将常量PI的值赋给常量P
	public final static double P = A.PI;
}

//定义接口实现类C,并多实现接口A、B、D
class C implements A,B,D{
	public void print() {
		System.out.println("接口A被实现类C已实现!"+P);
	}
	public void print1() {
		System.out.println("接口A和接口B被实现类C已多实现!"+PI);
	}
}

public class InterfaceTest {
	public static void main(String[] args) {
		C c = new C();
		c.print();
		c.print1();
	}

}
输出结果:
接口A被实现类C已实现!3.14
接口A和接口B被实现类C已多实现!3.14

 接口与抽象类的区别

接口抽象类
接口中的所有方法都是抽象的抽象类中的成员方法既可以是抽象的也可以不是抽象的
接口需要类来实现,然后创建实现类的对象抽象类需要类来继承,然后创建子类的对象
接口既可以多实现、多级继承接口,也可以多继承接口抽象类只能单继承和多级继承
接口中的成员变量为static final类型抽象类中的成员变量与一般类中的成员变量没有区别
接口中的成员方法默认是抽象的,不需要使用abstract修饰抽象类中的抽象方法需要使用abstract修饰

多态

  定义:同一个成员方法具有多个不同表现形式或形态的能力。

 继承多态

  定义:我们通常使用抽象类来抽象要使用多态的方法。
  特点:
 1.必须要有继承关系,在抽象类中可以定义多态的抽象方法,通过自理来继承这个抽象类,然后在子类中可以复写抽象类中的抽象方法,以达到多态的效果。
 2.多态子类的对象可以赋给父类的引用,但子类中特有的成员方法不能通过父类来调用

使用instanceof可以判断多态的引用对象为什么类型(与if···else等配合使用),其结果为布尔类型。

父类名 对象名 =  new 多态子类的对象名();

对象名 instanceof 多态子类的对象名
class Student{
	String name;
	//注意这里不是抽象方法
	public void study() {
	}
}

通常使用抽象类来抽象要使用多态的方法(下方为多态常用代码形式)
/*
abstract class Student{
	String name;
	//注意这里是抽象方法
	public abstract void study();
}
 */

class StudentA extends Student{
	@Override
	public void study() {
		System.out.println("继承多态!学生"+name);		
	}
}

class StudentB extends Student{
	@Override
	public void study() {
		System.out.println("继承多态!学生"+name);
	}
}

public class Test{
	public static void main(String[] args) {
		//注意,这里不是通过 “类名 对象名 = new 类名();”进行创建对象
		//而是使用 “父类名 对象名 =  new 多态的子类名();”进行创建对象
		Student studentA = new StudentA();
		studentA.name = "A";
		studentA.study();
		
		Student studentB = new StudentB();
		studentB.name = "B";
		studentB.study();	
	}
}

输出结果:
继承多态!学生A
继承多态!学生B
class Student{
	String name;
	//注意这里不是抽象方法
	public void study() {
	}
}

通常使用抽象类来抽象要使用多态的方法(下方为多态常用代码形式)
/*
abstract class Student{
	String name;
	//注意这里是抽象方法
	public abstract void study();
}
 */

class StudentA extends Student{
	@Override
	public void study() {
		System.out.print("学生"+name);
	}
}

class StudentB extends Student{
	@Override
	public void study() {
		System.out.print("学生"+name);	
	}
}
//创建老师类
class Teacher{
	public void checkHomework(Student s) {
		System.out.print("老师在检查");
		//接收时可以将学生的成员方法一起接收
		s.study();
		System.out.print("的作业"+"\n");	
	}
}

public class Test{
	public static void main(String[] args) {
		//注意,这里不是通过 “类名 对象名 = new 类名();”进行创建对象
		//而是使用 “父类名 对象名 =  new 多态的子类名();”进行创建对象
		Student studentA = new StudentA();
		studentA.name = "A";
		studentA.study();
		
		Student studentB = new StudentB();
		studentB.name = "B";
		studentB.study();
		System.out.println();
		
		Teacher teacher = new Teacher();
		//将学生对象作为参数传给checkHomework成员方法
		teacher.checkHomework(studentA);
		teacher.checkHomework(studentB);
	}
}
输出结果:
学生A学生B
老师在检查学生A的作业
老师在检查学生B的作业

 接口的多态

  接口的多态基本和类的继承的多态一致。不同的是类的继承使用的是继承关系实现多态,接口采用实现的方式实现多态。
可以使用构造器进行传值。
 语法:

接口名 对象名 = new 实现类名();

//定义接口A
interface A{
//	定义常量PI
	public final static double PI = 3.14;
//	定义抽象方法print
	public void print();
}

//定义接口实现类B,并实现接口A
class B implements A{
	public void print() {
		System.out.println("接口A被实现类B已实现!");
	}
}

//定义接口实现类C,并实现接口A
class C implements A{
	String name;
//	定义C类含参构造器
	public C(String name){
		this.name = name;
	}
	
	public void print() {
		System.out.println("接口A被实现类C已实现!"+"\t"+name);
	}
}

public class InterfaceTest {
	public static void main(String[] args) {
//		接口名 对象名 = new 实现类名();
		A b = new B();
		b.print();
		
		A a = new C("构造器传值测试!");
		a.print();
	}
}

输出结果:
接口A被实现类B已实现!
接口A被实现类C已实现!	构造器传值测试!

模板模式

  步骤:
 ①抽象模板(定义一个抽象类)
 ②必须要实现的一个业务方法(定义一个抽象方法)
 ③定义一个可重写也可不重写的方法
 ④定义一个不可被重写的方法(使用final修饰)
 ⑤定义一个模板方法,供其他类使用(按顺序调用成员方法)
 ⑥具体模板(使用子类继承抽象类)
 ⑦实现具体的业务逻辑(实现抽象类中的抽象方法)
 ⑧可重写也可不重写③的成员方法
 ⑨在测试类中创建具体模板的对象
 ⑩获得具体模板中的数据(返回值)

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值