为什么需要继承:为了解决代码复用性
基本介绍:继承可以解决代码复用,让我们的编程更靠近人类思维,当多个类存在相同的属性和方法时,可以从这些类中抽象出父类,在父类中定义这些相同的属性和方法,所有的子类不需要重新定义这些属性和方法,只需通过extends来声明继承父类即可
继承案例:
有a,b两名学生在考试,请用不同的两个类表示考试状态即考试结果
公共c类:
public class C { //公有属性 public String name; public int age; private int score; //公有方法: public void setScore(int score) { this.score = score; } public void info(){ System.out.println("学生名"+name+" "+"学生年龄"+age+" "+"成绩"+score); } }
A类:
public class A extends C{ public void testing(){ System.out.println("A学生"+name+"正在考试。。。"); } }
B类:
public class B extends C{ public void testing(){ System.out.println("B学生"+name+"正在考试。。。"); } }
测试Test类
public class Test { public static void main(String[] args){ A a = new A(); a.name = "roy"; a.age = 10; a.setScore(90); a.testing(); a.info(); System.out.println("====B===="); B b = new B(); b.age = 18; b.name = "karry"; b.testing(); b.setScore(100); b.info(); } }
细节
(1)子类继承了所有的属性和方法,非私有属性和方法可以在子类直接访问,但是私有属性和方法不能在子类直接访问,要通过公共的方法去访问
(2)子类必须调用父类的构造器,完成父类的初始化
(3)当创建子类对象是,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器,如果父类没有提供无参构造器,则必须在子类的构造器中用super去指定使用父类的哪个构造器完成对父类的初始化工作
解释:
公有C类:
public class C{ public String name; public int age; private int score; public C(String name,int age){ System.out.println("c被调用..."); } }
A类:
public class A extends C{ public A(){ super("karry",18); System.out.println("A被调用..."); } }
测试Test类:
public class Test{ public static void main(String[] args){ A a = new A; } }
输出:
(4)如果希望指定去调用父类的某个构造器,则显示的调用一下:supper(参数列表)
(5)super在使用时,必须放在构造器第一行
(6)super()和this()都只能放在构造器第一行,因此这两个方法不能共存在一个构造器
(7)java所有类都是Object类的子类,Object是所有类的基类
(8)父类构造器的调用不限于直接父类,将一直追溯到Object类(顶级父类)
(9)子类最多只能继承一个父类()指直接继承,即Java中是单继承机制
(10)不能滥用继承,子类和父类之间必须满足is-a的逻辑关系
例子:父类:Animal
子类:Cat
cat is a animal(猫是一种动物)
(1)编写Computer类,包含cpu,内存,硬盘等属性,getDetail方法用于返回Computer的详细信息
(2)编写PC子类,继承Computer类,添加特有属性【brand】
(3)编写NotePad子类,继承Computer类,添加特有属性【color】;
(4)编写Test类,在main方法中创建PC和NotePad对象,分别给对象中特有的属性赋值,以及从Computer类继承的属性赋值,并打印出信息
Computer类:
public class Computer { //公有属性 private String cpu; private int nc; private int yp; public C(String cpu, int nc, int yp) { this.cpu = cpu; this.nc = nc; this.yp = yp; } public String getCpu() { return cpu; } public void setCpu(String cpu) { this.cpu = cpu; } public int getNc() { return nc; } public void setNc(int nc) { this.nc = nc; } public int getYp() { return yp; } public void setYp(int yp) { this.yp = yp; } public String getDetails(){ return "cpu="+cpu+" "+"内存="+nc+" "+"硬盘"+yp; } }
PC类
public class PC extends Computer { private String brand; public A(String cpu, int nc, int yp, String brand) { super(cpu, nc, yp); this.brand = brand; } public String getBrand() { return brand; } public void info(){ System.out.println(getDetails()+"brand="+brand); } }
NotePad类:
public class B extends Computer{ private String color; public B(String cpu, int nc, int yp, String color) { super(cpu, nc, yp); this.color = color; } public void setColor(String color) { this.color = color; } public void info(){ System.out.println(getDetails()+"color="+color); } }
Test类:
public class Test { public static void main(String[] args){ A a = new A("intel",18,20,"dell"); a.info(); B b = new B("amd",20,13,"hp"); b.info(); } }
super关键字(跳过本类,直接访问父类)
基本介绍:super代表父类的引用,用于访问父类的属性,方法,构造器
注意
(1)访问父类的属性,但不能访问父类的private属性
(2)访问父类的方法,不能访问父类的private方法
(3)访问构造器,记得得写在构造器里,还要注意必须写在第一行
区别点 | this | super | |
---|---|---|---|
1 | 访问属性 | 访问本类中的属性,如果本类中没有此属性则从父类中继续查找 | 从父类开始查找属性 |
2 | 调用方法 | 访问本类中的方法,如果本类没有此方法则从父类继续查找 | 从父类开始查找方法 |
3 | 调用构造器 | 调用本类构造器,必须放在构造器的首行 | 调用父类构造器,必须放在子类构造器的首行 |
4 | 特殊 | 表示当前对象 | 子类中访问父类对象 |
方法重写
简单介绍:方法覆盖(重写)就是子类有一个方法,和父类的某个方法的名称、返回类型、参数一样,那么我们就说子类的这个方法覆盖了父类的那个方法
细节:
(1)子类的方法参数,方法名称要和父类的完全一样
(2)子类方法的返回类型和父类方法返回类型一样,或者是父类返回类型的子类比如:父类返回类型是Object,子类方法返回的类型是String就是可以的
(3)子类方法不能缩小父类方法的访问权限
名称 | 发生范围 | 方法名 | 参数列表 | 返回类型 | 修饰符 |
---|---|---|---|---|---|
重载 | 本类 | 必须一样 | 类型个数或顺序至少有一个不同 | 无要求 | 无要求 |
重写 | 父子类(存在于继承中) | 必须一样 | 必须相同 | zi类重写的方法,返回的类型和父类返回的类型一致,或者是其子类 | 子类方法不能缩小父类的访问范围 |
练习
(1)编写一个person类,包括属性(private(name,age)),构造器、方法say(返回自我介绍的字符串)
(2)编写一个Student类,继承Person类,增加id,score属性(private),以及构造器,定义say方法(返回自我介绍信息)
(3)在main中,分别创建Person和Student对象,调用say方法输出自我介绍
Person类
public class Person { public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } private String name; private int age; public C(String name, int age) { this.name = name; this.age = age; } public String say(){ return "大家好,我的名字是"+name+",我今年"+age+"了"; } }
Student类
public class Student extends Person { private int id; private double score; public int getId() { return id; } public double getScore() { return score; } public A(String name, int age, int id, double score) { super(name, age); this.id = id; this.score = score; } public String say() { return super.say()+ ",我的学号是"+id+",我的成绩是"+score; } }
main类
public class main { public static void main(String[] args){ A a = new A("KARRY",18,44,99); System.out.println(a.say()); C c = new C("Roy",18); System.out.println(c.say()); } }