面向对象 四
1.继承带来的问题
1.1 父类中的方法不一定适合子类
开发中父类的方法继承给子类使用,但是子类使用不太符合子类的情况,如果子类方法重新定义,重新命名,又会导致代码冗余,开发压力较大。
1.2 重写 【Override】
前提条件:
1. 重写是存在与继承中子类,或者【遵从代码实现类】
2. 重写情况下要求子类中的方法和父类中的方法,方法声明完全一致。
3. 方法体按照子类的情况来完成
注意事项:
1. 子类重写父类方法,要求必须加上@Override严格格式检查。
2. @Override会检查子类重写的方法,方法声明是否和父类一致
1.3 重写能解决所有问题吗?
继承情况下:
1. 父类的方法不符合子类情况
2. 需要重写的情况下,但是子类不重写没有任何语法错误
3. 会导致代码在实际运行阶段不符合生活逻辑和需求
【强制重写】
2. abstract关键字 【难点,但是又很简单】
2.1 abstract概述
【前提】
abstract修饰的方法,子类必须重写
2.2 abstract 关键字代码使用和注释
package com.qfedu.c_abstract;
/**
* LOL英雄类,每一个英雄都有QWER技能
*
* @author Anonymous
*/
/*
* 第一步:
* 使用abstract关键字修饰要求子类重写的方法
* 【方法报错】
* Abstract methods do not specify a body
* abstract修饰的方法没有方法体
* 【Eclipse快速修复】
* Ctrl + 1
* 选择 Remove Method Body 删除方法体
*
* 第二步:
* 【方法报错】
* The abstract method q in type LOLHero can only be defined by an abstract class
* LOLHero类内的abstract修饰方法q(),有且只能定义在一个abstract修饰的类内
* 【类名报错】
* The type LOLHero must be an abstract class to define abstract methods
* LOLHero类必须是一个abstract类,才可以定义abstract方法
* 【语法要求】
* abstract修饰的方法,必须在定义在abstract修饰的类内或者XXXXXXXXXXXXXXXXXXXXXXXXX
* 【Eclipse快速修复】
* Ctrl + 1
* 选择 Make Type 'LOLHero' abstract 使用abstract修饰LOLHero类
*
* 第三步:
* 【子类报错】
* The type Thresh must implement the inherited abstract method LOLHero.q()
* Thresh类必须实现继承LOLHero类内的abstract方法q
* 因为abstract修饰的方法,在父类abstract类内没有方法体,子类如果想要使用abstract修饰的方法
* 必须完成方法体的实现
* 【Eclipse快速修复】
* Ctrl + 1
* 选择 Add unimplemented methods 添加未实现方法
*/
abstract class LOLHero {
abstract public void q();
abstract public void w();
abstract public void e();
abstract public void r();
}
/**
* 锤石类继承LOLHero类
*
* @author Anonymous
*
*/
class Thresh extends LOLHero {
@Override
public void q() {
System.out.println("死亡判决");
}
@Override
public void w() {
System.out.println("魂引之灯");
}
@Override
public void e() {
System.out.println("厄运钟摆");
}
@Override
public void r() {
System.out.println("幽冥监牢");
}
}
/**
* 维鲁斯类继承LOLHero类
*
* @author Anonymous
*
*/
class Varus extends LOLHero {
@Override
public void q() {
System.out.println("穿刺之箭");
}
@Override
public void w() {
System.out.println("枯萎箭袋");
}
@Override
public void e() {
System.out.println("恶灵箭雨");
}
@Override
public void r() {
System.out.println("腐败链锁");
}
}
public class Demo1 {
public static void main(String[] args) {
Thresh saolei = new Thresh();
saolei.q();
saolei.e();
saolei.w();
saolei.r();
System.out.println("--------------------------");
Varus varus = new Varus();
varus.q();
varus.w();
varus.e();
varus.r();
}
}
2.3 abstract使用特征
1. abstract修饰方法 没有方法体
2. abstract修饰的方法,要求定义在abstract修饰的类内,或者接口interface内
3. abstract修饰的类,没有类对象
abstract修饰的类内,是有可能存在abstract修饰的方法,而abstract修饰的方法是没有方法体的,如果能够得到一个abstract修饰类的对象,通过对象如何调用这些没有方法体的abstract方法。
4.abstract修饰的类,然后类内没有任何一个abstract修饰的方法,毫无意义
3. 重载【Overload】
3.1 重载要求
要求:
1. 重载是要求在统一类内,或者interface内
2. 重载要求方法名必须一致!!!
3. 重载对于方法的参数必须不一致!!!
4.重载对于方法返回值没有任何约束!!!
3.2 重载能够解决的问题
1. 简化代码结构,在同一个类内同名方法功能一致,但是参数满足多样化。
2.简化程序员开发压力
3.能够做到统一处理方式
3.3 代码演示
package com.qfedu.d_overload;
class Person {
public void game() {
System.out.println("大吉大利,今晚吃鸡");
}
public void game(String name) {
System.out.println("玩" + name);
}
public int game(String name, int time) {
System.out.println("玩" + time + "个小时" + name);
return 1;
}
}
public class Demo1 {
public static void main(String[] args) {
Person person = new Person();
person.game();
person.game("LOL");
person.game("WOT", 2);
}
}
4. this关键字补充
4.1 在统一个构造方法中,通过this关键字调用其它的构造方法
格式:
1. 要求在一个构造方法中,Constructor
2. this(实际参数);
3. 会根据实际参数的类型,个数,顺序来选择对应的构造方法。
4.3 代码演示和总结
package com.qfedu.d_overload;
/*
* this关键字在一个构造方法,调用其他构造方法
* 注意事项:
* 1. 不能通过this关键字调用当前所在构造方法,无穷递归!!!错误!!!
* 2. this(实际参数); 根据实际参数的类型,个数和顺序来完成的
* 3. Constructor call must be the first statement in a constructor
* 通过this关键字调用其他构造方法,必须在当前方法体的第一行!!!
* 4. 能不能在一个构造方法中,通过this关键字,同时调用两个构造方法???
* 不能!!!因为构造方法调用必须在第一行,如果存在两个必然有一个在第二行,语法报错
* 5. 两个构造方法,能不能通过this关键字相互调用???
* 不允许,无穷递归!!!
* 6. 规范化,统一化方法执行操作,提高代码的安全性和一致性!!!
*
*/
class Dog {
private String name;
private String color;
private int age;
public Dog() {
this(null, null, 0);
}
public Dog(String name) {
this(name, null, 0);
}
public Dog(String name, String color) {
this(name, color, 0);
}
public Dog(String name, String color, int age) {
this.name = name;
this.color = color;
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
public class Demo2 {
}
5. super关键字【鸡肋】
5.1 super关键字作用
1. super关键字可以用于在子类和父类之间,同名成员变量,同名成员方法调用时明确区分。2. super关键字可以显式调用父类的构造方法,用于初始化父类的成员变量数据。
3. super关键字使用的格式,规范和this非常类似。
5.2 代码演示
5.2.1 super关键字区分成员变量和成员方法
package com.qfedu.e_super;
class Father {
public String name;
public String age;
public void game() {
System.out.println("黄金矿工");
}
}
class Son extends Father {
public String name;
public String age;
@Override
public void game() {
System.out.println("PUBG");
}
public void test() {
// 调用子类的成员方法,就近元素
game();
// super关键字调用父类的game方法
super.game();
// 调用子类成员变量
name = "大头儿子";
// super关键字调用父类的成员变量
super.name = "隔壁老王";
}
}
public class Demo1 {
}
5.2.2 super关键字调用构造方法
package com.qfedu.e_super;
/*
* super关键字在子类构造方法中,调用父类构造方法
* 格式:
* super(实际参数);
* 会根据实际参数来选择使用父类对应数据类型,个数,顺序的构造方法,用于初始化父类的
* 成员变量数据。
*
* 注意事项:
* 1. 在没有指定选择哪一个父类构造构造方法,作为子类初始化父类成员变量空间的操作时
* Java编译器会默认选择父类的无参数构造方法。
* 2. 选择使用父类的有参数构造方法,初始化父类成员变量空间
* 3. 父类数据的交给父类的构造方法操作,不要在子类中操作。
* 4. super关键字显式调用父类的构造方法,必须在代码的第一行
* 5. super关键字调用构造方法,和this关键字调用构造方法,是否能共存???
* 【显式】情况下不可以!!!
* 但是省略通过super关键字调用父类构造方法的情况下,Java编译器会在
* 编译的过程中,默认选择无参数父类构造方法使用
*/
class Animal {
private String name;
public Animal() {
System.out.println("Animal无参数构造方法");
}
public Animal(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
class Cat extends Animal {
private String color;
public Cat() {
System.out.println("Cat无参数构造方法");
}
public Cat(String color) {
this();
this.color = color;
System.out.println("Cat有参数构造方法");
}
public Cat(String color, String name) {
super(name);
this.color = color;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
public class Demo2 {
public static void main(String[] args) {
Cat cat = new Cat("玳瑁猫");
}
}
6. final关键字
6.1 基本语法
最终!!!
final关键字可以修饰
局部变量 有且只能被赋值一次,赋值之后不可以修改
成员变量 定义时必须初始化,未初始化报错
成员方法 使用final修饰的方法为最终方法,不能被重写!!!
类 没有子类,不能被继承
Java中是存在一些类是使用final修饰的
String类
package com.qfedu.f_final;
/*
final关键字可以修饰
局部变量 有且只能被赋值一次,赋值之后不可以修改
成员变量 定义时必须初始化,未初始化报错
成员方法 使用final修饰的方法为最终方法,不能被重写!!!
类 没有子类,不能被继承
Java中是存在一些类是使用final修饰的
String类
*/
final class Father {
final public void game() {
System.out.println("黄金矿工!!!");
}
}
// The type Son cannot subclass the final class Father
// Son类不能是final修饰的类Father类的子类,不能继承Father
// class Son extends Father {
// The blank final field age may not have been initialized
// 使用final修饰的成员变量还没有被初始化
// final int age = 10;
// Cannot override the final method from Father
// 使用final修饰的方法为最终方法,不能被重写!!!
// public void game() {
// System.out.println("PUBG");
// }
// }
public class Demo1 {
public static void main(String[] args) {
final int num;
num = 10;
// The final local variable num may already have been assigned
// 使用final修饰的局部变量num已经被赋值
// num = 20;
}
}
7.2 思考题
package com.qfedu.f_final;
class Dog {
String name;
int age;
}
public class Demo2 {
public static void main(String[] args) {
Dog dog = new Dog();
dog.name = "八公";
dog.age = 15;
/*
* final修饰的是dog1,dog1是一个类对象,同时是一个引用数据类型的变量。
* dog1存储数据不可以改变!!!dog1指向不可以改变,但是dog1指向空间中的内容可以改变。
*
* dog1看作你你的房产证,房产证上面的地址是不可以改变的!!!
* 但是房子装修和房产证有关吗?
*/
final Dog dog1 = new Dog();
// dog1能不能操作成员变量???
dog1.name = "骚杰";
dog1.age = 16;
// 能不能修改???
dog1.name = "一杯二锅头";
dog1.age = 20;
Dog dog2 = dog1;
dog2 = new Dog();
// The final local variable dog1 cannot be assigned.
// It must be blank and not using a compound assignment
// dog1 = new Dog();
}
}
关键字在子类构造方法中,调用父类构造方法
- 格式:
-
super(实际参数);
-
会根据实际参数来选择使用父类对应数据类型,个数,顺序的构造方法,用于初始化父类的
-
成员变量数据。
- 注意事项:
-
1. 在没有指定选择哪一个父类构造构造方法,作为子类初始化父类成员变量空间的操作时
-
Java编译器会默认选择父类的无参数构造方法。
-
2. 选择使用父类的有参数构造方法,初始化父类成员变量空间
-
3. 父类数据的交给父类的构造方法操作,不要在子类中操作。
-
4. super关键字显式调用父类的构造方法,必须在代码的第一行
-
5. super关键字调用构造方法,和this关键字调用构造方法,是否能共存???
-
【显式】情况下不可以!!!
-
但是省略通过super关键字调用父类构造方法的情况下,Java编译器会在
-
编译的过程中,默认选择无参数父类构造方法使用
*/
class Animal {
private String name;
public Animal() {
System.out.println("Animal无参数构造方法");
}
public Animal(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
class Cat extends Animal {
private String color;
public Cat() {
System.out.println("Cat无参数构造方法");
}
public Cat(String color) {
this();
this.color = color;
System.out.println("Cat有参数构造方法");
}
public Cat(String color, String name) {
super(name);
this.color = color;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
public class Demo2 {
public static void main(String[] args) {
Cat cat = new Cat("玳瑁猫");
}
}
6. final关键字
6.1 基本语法
最终!!!
final关键字可以修饰
局部变量 有且只能被赋值一次,赋值之后不可以修改
成员变量 定义时必须初始化,未初始化报错
成员方法 使用final修饰的方法为最终方法,不能被重写!!!
类 没有子类,不能被继承
Java中是存在一些类是使用final修饰的
String类
package com.qfedu.f_final;
/*
final关键字可以修饰
局部变量 有且只能被赋值一次,赋值之后不可以修改
成员变量 定义时必须初始化,未初始化报错
成员方法 使用final修饰的方法为最终方法,不能被重写!!!
类 没有子类,不能被继承
Java中是存在一些类是使用final修饰的
String类
*/
final class Father {
final public void game() {
System.out.println("黄金矿工!!!");
}
}
// The type Son cannot subclass the final class Father
// Son类不能是final修饰的类Father类的子类,不能继承Father
// class Son extends Father {
// The blank final field age may not have been initialized
// 使用final修饰的成员变量还没有被初始化
// final int age = 10;
// Cannot override the final method from Father
// 使用final修饰的方法为最终方法,不能被重写!!!
// public void game() {
// System.out.println("PUBG");
// }
// }
public class Demo1 {
public static void main(String[] args) {
final int num;
num = 10;
// The final local variable num may already have been assigned
// 使用final修饰的局部变量num已经被赋值
// num = 20;
}
}
7.2 思考题
package com.qfedu.f_final;
class Dog {
String name;
int age;
}
public class Demo2 {
public static void main(String[] args) {
Dog dog = new Dog();
dog.name = "八公";
dog.age = 15;
/*
* final修饰的是dog1,dog1是一个类对象,同时是一个引用数据类型的变量。
* dog1存储数据不可以改变!!!dog1指向不可以改变,但是dog1指向空间中的内容可以改变。
*
* dog1看作你你的房产证,房产证上面的地址是不可以改变的!!!
* 但是房子装修和房产证有关吗?
*/
final Dog dog1 = new Dog();
// dog1能不能操作成员变量???
dog1.name = "骚杰";
dog1.age = 16;
// 能不能修改???
dog1.name = "一杯二锅头";
dog1.age = 20;
Dog dog2 = dog1;
dog2 = new Dog();
// The final local variable dog1 cannot be assigned.
// It must be blank and not using a compound assignment
// dog1 = new Dog();
}
}