继承
- 为什么需要继承:为了解决代码复用性
- 基本介绍:继承可以解决代码复用,让我们的编程更靠近人类思维,当多个类存在相同的属性和方法时,可以从这些类中抽象出父类,在父类中定义这些相同的属性和方法,所有的子类不需要重新定义这些属性和方法,只需通过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的比较
区别点 | 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());
}
}