-
继承
在继承的关系中,子类就是一个父类,也就是说,子类可以被当做父类看待
例如:父类是员工,子类是程序员,那么程序员就是一个员工
// 员工类 public class Employee{ String name; int age; } // 程序员类(继承员工类) public class Programer extends Employee{ } // 主方法 public class Extends { public static void main(String[] args) { Programer coder = new Programer(); coder.name = "johny"; coder.age = 20; System.out.println(coder.name + " " + coder.age); // johny 20 } }
在父子类的继承关系当中,如果成员变量重名,则创建子类对象时,访问有两种方式:
1. 直接通过子类对象访问成员变量:(优先使用自己的,没有则向上找)
2. 间接通过成员方法访问成员变量:(看方法属于谁,就优先用谁的,没有则往上找,找不到就报错)在父子类的继承关系中,创建子类对象,访问成员方法的规则:
1. 创建的对象是谁,就优先用谁,如果没有就向上找无论是成员方法还是成员变量,如果没有都是向上找父类,绝对不会向下找子类的
-
区分子类方法中重名的三种变量
- 局部变量: 直接写成员变量名
- 本类中的成员变量: this.成员变量名
- 父类中的成员变量: super.成员变量名
-
继承中方法的覆盖
覆盖与方法的重载不同:同样是方法名相同,但覆盖指接收的参数也相同
注意事项:
-
在子类方法前面写上
@Override
,用来检测是不是有效的正确覆盖重写 -
子类方法的返回值必须小于等于父类方法的返回值范围(例如:子类返回String,父类返回Object)
-
子类方法的权限必须大于等于父类方法的权限修饰符
public > protected > (default) > private
// 父类 public class Phone { public void call(){ System.out.println("call"); } public void send(){ System.out.println("send"); } } // 子类 public class NewPhone extends Phone{ // 方法权限必须大于等于父类 public void call(){ // 调用父类方法 super.call(); // 添加自己的逻辑 System.out.println("show picture"); } } public class DemoCover { public static void main(String[] args) { NewPhone newPhone = new NewPhone(); newPhone.call(); // call \n show picture } }
-
-
继承中构造方法的访问特点
Notice:
- 子类构造方法中有一个默认隐含的 “super()” 调用,所以一定是先调用的父类构造,再调用的子类构造
- 子类构造可以通过 “super” 关键字来调用父类的重载构造(当父类含有多个构造方法)
- super 的父类构造方法调用,必须是子类构造方法的第一条语句,且只能调用一次 super 构造
sum up:子类必须调用父类的构造方法,不写则赠送 super() ,写了就调用指定的 super 。
-
super 关键字的三种用法
- 在子类的成员方法中,使用 super 得到父类的成员变量
- 在子类的成员方法中,使用 super 访问父类的成员方法
- 在子类的构造方法中,使用 super 访问父类的构造方法
-
this 关键字的三种用法
super 关键字用来访问父类内容,而 this 关键字用来访问本类内容
-
在本类的成员方法中,使用 this 得到本类中的成员变量
-
在本类的成员方法中,使用 this 访问本类中的成员方法
-
在本类的构造方法中,使用 this 调用本类的重载构造方法(另一个构造方法)
this(…) 调用也必须是构造方法中的第一条语句,且只能使用一次
super 和 this 两种构造使用,不能同时使用
-
-
this 和 super 关键字图解
-
继承的三个特点图解
-
抽象方法和抽象类
抽象方法:就是在 void 前面加上 abstract 关键字,然后去掉大括号,直接分号结束
抽象类:抽象方法所在的类,必须是抽象类,在 class 前面加上 abstract 关键字即可
// 这是一个抽象类 public abstract class Animal{ // 这是一个抽象方法,代表吃东西,具体吃什么?不知道 public abstract void eat(); }
如何使用抽象类和抽象方法?
- 不能直接 new 抽象类,必须使用子类继承抽象父类
- 非抽象子类必须覆盖抽象父类的所有的抽象方法
- 创建非抽象子类对象进行使用
Notice:
- 抽象类中,可以有构造方法,是供非抽象子类创建对象时,初始化父类成员使用的
- 抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类
// 抽象父类 public abstract class Animal{ public Animal(){ System.out.println("抽象父类构造方法执行"); } // 抽象方法 public abstract void eat(); public abstract void sleep(); } // 抽象子类 public abstract class Dog extends Animal{ @Override public void eat(){ System.out.println("dog eat meat"); } } // 间接子类 public class JinMao extends Dog { @Override public void sleep(){ System.out.println("JinMao in his sleeping"); } } public class HaShiQi extends Dog { @Override public void sleep(){ System.out.println("HaShiQi in his sleeping"); } } public class DemoAbstract{ public static void main(String[] args){ JinMao jinMao = new JinMao(); jinMao.eat(); jinMao.sleep(); HaShiQi haShiQi = new HaShiQi(); haShiQi.eat(); haShiQi.sleep(); } } // 执行结果 抽象父类构造方法执行 dog eat meat JinMao in his sleeping 抽象父类构造方法执行 dog eat meat HaShiQi in his sleeping
-
发红包案例
// User基类
public class User {
private String name;
private int money;
public User(){
}
public User(String name, int money){
this.name = name;
this.money = money;
}
public void setName(String name){
this.name = name;
}
public String getName(){
return this.name;
}
public void setMoney(int money){
this.money = money;
}
public int getMoney(){
return this.money;
}
public void show(){
String str = String.format("my name is %s, i have %d yuan ", this.name, this.money);
System.out.println(str);
}
}
// 群主类
import java.util.ArrayList;
import java.util.Scanner;
public class Manager extends User{
public Manager(){
}
public Manager(String name, int money){
super(name, money);
}
// 发红包
public ArrayList<Integer> send(){
while (true){
// 确定发多少钱,发多少个?
Scanner scanner = new Scanner(System.in);
int money = scanner.nextInt();
int count = scanner.nextInt();
if (money > super.getMoney()) {
String str = String.format("your balance is %d! place re-select", super.getMoney());
System.out.println(str);
continue;
}
// 确定每个红包有多少钱
int avg = money / count;
int remainder = money % count; // 余数,就是零头
// 塞钱进红包, 使用集合表示红包
ArrayList<Integer> set = new ArrayList<>();
for (int i = 0; i < count - 1; i++) {
set.add(avg);
}
// 把零头塞进最后一个红包里面
set.add(avg + remainder);
// 减去余额
super.setMoney(super.getMoney() - money);
return set;
}
}
}
// 成员类
import java.util.ArrayList;
import java.util.Random;
public class Member extends User{
public Member(){
}
public Member(String name, int money){
super(name, money);
}
// 收红包
public void receive(ArrayList<Integer> set){
// 随机收一个红包
Random random = new Random();
int index = random.nextInt(set.size());
int cash = set.remove(index);
String str = String.format("i got was %d yuan", cash);
System.out.println(str);
// 修改余额
super.setMoney(super.getMoney() + cash);
}
}
// 程序运行入口
import java.util.ArrayList;
public class DemoStart {
public static void main(String[] args){
// 建群,拉人
Manager manager = new Manager("Manager", 100);
Member mbA = new Member("mbA", 0);
Member mbB = new Member("mbB", 0);
Member mbC = new Member("mbC", 0);
manager.show();
mbA.show();
mbB.show();
mbC.show();
// 发红包
ArrayList<Integer> set = manager.send();
// 收红包
mbA.receive(set);
mbB.receive(set);
mbC.receive(set);
// 活动结束后各自有多少钱?
manager.show();
mbA.show();
mbB.show();
mbC.show();
}
}