多个类可以称为子类,单独那一个类称为父类、超类(superclass)或者基类
继承:就是子类继承父类的属性和行为,使得子类对象具有与父类相同的属性、相同的行为。子类可以直接访问父类中的非私有的属性和行为。
好处
-提高代码的复用性。
public class Employee { String name; public void work(){ System.out.println("快乐的工作着"); } }
子类
public class Teacher extends Employee{ public void printName(){ System.out.println("name = " + name); } }
测试
public class Test { public static void main(String[] args) { Teacher teacher = new Teacher(); teacher.name = "小明"; teacher.printName(); teacher.work(); } }
public class Fu { int num = 5; } public class ZI extends Fu{ int num2 = 6; public void show(){ System.out.println("num = " + num); System.out.println("num2 = " + num2); } } public class Test { public static void main(String[] args) { ZI zi = new ZI(); zi.show(); } }
重名
public class Fu { int num = 5; } public class ZI extends Fu { int num = 6; public void show(){ System.out.println("Fu = " + super.num); System.out.println("zi = " + this.num); } } public class Test { public static void main(String[] args) { ZI zi = new ZI(); zi.show(); } }
小贴士:Fu类中的成员变量是非私有的,子类中可以直接访问。若Fu
类中的成员变量私有了,子类是不能直接访问的。通常编码时,我们遵循封装的原则,使用private修饰成员变量,那么如何访问父类的私有成员变量呢?对!可以在父类中提供公共的getXxx方法和setXxx方法。
会先在子类中查找有没有对应的方法
,若子类中存在就会执行子类中的方法,public class Fu { public void show(){ System.out.println("Fu show()"); } } public class ZI extends Fu { public void show2(){ System.out.println("Zi show2()"); } } public class Test { public static void main(String[] args) { ZI zi = new ZI(); zi.show2(); zi.show(); } }
子类中出现与父类一模一样的方法时(返回值类型,方法名和参数列表都相同),会出现覆盖效果,也称为重写
或者复写
。声明不变,重新实现
public class Fu { public void show(){ System.out.println("Fu show()"); } } public class ZI extends Fu { public void show(){ System.out.println("Zi show()"); } }
重写的应用
public class Phone { public void sendMessage() { System.out.println("发短信"); } public void call() { System.out.println("打电话"); } public void showNum() { System.out.println("来电显示号码"); } } package com.claire.day07.demo5; public class NewPhone extends Phone{ @Override public void showNum() { // 调用父类的同名方法 super.showNum(); System.out.println("显示来电的头像"); } } public class Test { public static void main(String[] args) { NewPhone newPhone = new NewPhone(); newPhone.showNum(); } }
注意:
首先我们要回忆两个事情,构造方法的定义格式和作用。
public class Fu { private int n; Fu(){ System.out.println("Fu 构造"); } } public class ZI extends Fu { ZI(){ super(); // 先调用父类的构造方法 这里不写也会调用 System.out.println("ZI() 构造"); } } public class Test { public static void main(String[] args) { new ZI(); } }
父类空间优先于子类对象产生
在每次创建子类对象时,先初始化父类空间,再创建其子类对象本身。目的在于子类对象中包含了其对应的父类空
间,便可以包含其父类的成员,如果父类成员非private修饰,则子类可以随意使用父类成员。代码体现在子类的构造方法调用时,一定先调用父类的构造方法
1.访问成员
this.成员变量 本类的 super.成员变量 父类的 this.成员方法名() 本类的 super.成员方法名() 父类的
this(...) 本类的构造方法 super(...) 父类的构造方法
顶层父类是Object类。所有的类默认继承Object,作为父类。
public boolean equals(Object obj) { return (this == obj); }
public boolean equals(Object anObject) { if (this == anObject) { return true; } // instanceof String 是否属于String类型 if (anObject instanceof String) { // 强制转换为 String类型 String anotherString = (String)anObject; int n = value.length; if (n == anotherString.value.length) { char v1[] = value; char v2[] = anotherString.value; int i = 0; while (n-- != 0) { if (v1[i] != v2[i]) return false; i++; } return true; } } return false; }
public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode()); }
父类中的方法,被它的子类们重写,子类各自的实现都不尽相同。那么父类的方法声明和方法主体,只有声明还有意义,而方法主体则没有存在的意义了。我们把没有方法主体的方法称为抽象方法。Java语法规定,包含抽象方法的类就是抽象类。
修饰符 abstract 返回值类型 方法名 (参数列表)
抽象类
如果一个类包含抽象方法,那么该类必须是抽象类。
public abstract class Animal { public abstract void run(); }
继承抽象类的子类必须重写父类所有的抽象方法。否则,该子类也必须声明为抽象类。最终,必须有子类实现该父类的抽象方法,否则,从最初的父类到最终的子类都不能创建对象,失去意义。
public abstract class Animal { public abstract void run(); public void sleep(){ System.out.println("在睡觉"); } } public class Cat extends Animal{ @Override public void run() { System.out.println("鸟悄的跑二"); } } public class Test { public static void main(String[] args) { Cat cat = new Cat(); cat.run(); cat.sleep(); } }
此时的方法重写,是子类对父类抽象方法的完成实现,我们将这种方法重写的操作,也叫做实现方法。
package com.weida.day02; /** * @ Author :Eric Lee * @ Date :Created in 23:33 2022/1/28 * @ Description: * @ Modified By: * @ Version : 1.0 */ public class User { private String userName; private double leftMoney; public User() { } public User(String userName, double leftMoney) { this.userName = userName; this.leftMoney = leftMoney; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public double getLeftMoney() { return leftMoney; } public void setLeftMoney(double leftMoney) { this.leftMoney = leftMoney; } @Override public String toString() { return "User{" + "userName='" + userName + '\'' + ", leftMoney=" + leftMoney + '}'; } }
群主
package com.weida.day02; import java.util.ArrayList; /** * @ Author :Eric Lee * @ Date :Created in 23:35 2022/1/28 * @ Description: * @ Modified By: * @ Version : 1.0 */ public class QunZhu extends User{ public QunZhu() { } public QunZhu(String userName, double leftMoney) { super(userName, leftMoney); } // 发等额红包 public ArrayList<Double> send1(int money, int count){ double leftMoney = this.getLeftMoney(); if (leftMoney < money){ return null; } // 更新 this.setLeftMoney(leftMoney-money); // 等分 money*=100; //每一份 int m = money/count; int l = money%count; ArrayList<Double> list = new ArrayList<>(); for (int i = 0; i < count-1; i++) { list.add(m/100.0); } if(l==0) list.add(m/100.0); else list.add((m+l)/100.0); return list; } // 发手气红包 // public ArrayList<Double> send2(int money, int count){ // // } }
成员
package com.weida.day02; import java.util.ArrayList; import java.util.Random; /** * @ Author :Eric Lee * @ Date :Created in 23:44 2022/1/28 * @ Description: * @ Modified By: * @ Version : 1.0 */ public class Member extends User{ public Member() { } public Member(String userName, double leftMoney) { super(userName, leftMoney); } public void open(ArrayList<Double> list){ Random random = new Random(); int index = random.nextInt(list.size()); Double money = list.remove(index); this.setLeftMoney(money + this.getLeftMoney()); } }
测试
package com.weida.day02; import java.util.ArrayList; /** * @ Author :Eric Lee * @ Date :Created in 23:05 2022/1/28 * @ Description: * @ Modified By: * @ Version : 1.0 */ public class TestRedPacket { public static void main(String[] args) { // User类 属性: username 和 leftMoney // QunZhu类 发红包 send(iny moeny, int count) 返回 ArrayList<Double> list // Member类 开红包 open (ArrayList<Double> list) 随机选一个 // ArrayList<Object> list = new ArrayList<>(); // list.remove() QunZhu qunZhu = new QunZhu("马化腾", 1000); ArrayList<Double> list = qunZhu.send1(100, 3); System.out.println(list); Member member1 = new Member("张三1", 10); Member member2 = new Member("张三2", 20); Member member3 = new Member("张三3", 30); member1.open(list); member2.open(list); member3.open(list); System.out.println(qunZhu); System.out.println(member1); System.out.println(member2); System.out.println(member3); } }