知识回顾
(1)类和对象的理解?
对象是现实世界中的一个实体,如一个人、一辆汽车。一个对象一般具有两方面的特征,状态和行为。状态用来描述对象的静态特征,行为用来描述对象的动态特征。
类是具有相似特征和行为的对象的集合,是对象共同特征的描述。
类和封装的关系:类是对象的抽象,对象(通常也称实例)是类的一个具体实例。
(2)面向对象三大特性?
封装、继承和多态。
(3)封装性的理解?
封装性一方面是把对象的属性和行为看成一个密不可分的整体,将这两者“封装”在一个不可分割的独立单元中;另一方面是将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问。
1.1. 继承的概念
(1)现实中的继承
现实生活中,说到继承,通常会想到子女继承父辈的财产、事业等。
(2)程序中的继承
在程序中,继承描述的是事物之间的所属关系,通过继承可以使多种事物之间形成一种关系体系。例如,老师和学生都属于人类,程序中便可以描述为:老师和学生继承自人类,同理,体育老师和美术老师继承自老师,而专科生和本科生继承自学生。
1.2. 继承的思路
(1)为什么要使用继承
思考,如下两个类有什么问题或可优化点呢?Student和Teacher类中存在着相同的成员变量和成员方法。
(2)使用继承优化设计
使用继承优化设计,将Student和Teacher类中重复的代码提取到父类(Person)中。
(3)使用继承优化后
继承提高了代码的复用性,多个类相同的成员可以放到同一个类中;提高了代码的维护性,如果方法的代码需要修改,修改一处即可。
(4)思考
思考提问环节,现实中还有哪些对象存在继承性呢?举例说明父子的继承关系。
(5)思政
在工作和生活中的实践中,我们要学会继承的思想,“站在巨人的肩膀上前进”。
1.3. 继承的实现
(1)编写父类
不同类会有一些共同的特征和行为,将这些共同的特征和行为统一放到一个类中,这个类可以作为父类。
public class 父类{//公共的属性和方法
}
(2)编写子类,继承父类
声明子类继承父类,需要使用extends关键字,继承可以使得子类具有父类的属性和方法,还可以在子类中重新定义、追加属性和方法。
其语法格式如下所示:
public class 子类 extends 父类{//子类特有的属性和方法
}
-
案例需求
定义一个人类(Person),定义成员变量姓名(String name)和年龄(int age),成员变量都是public修饰;定义成员方法eat( ),在其中输出“吃饭”,成员方法用public修饰。
定义一个学生类(Student),它继承Person类,定义成员变量学号(String stuCode),成员变量用public修饰。
编写程序,使用无参构造方法实现Student类的实例化,对成员变量姓名、年龄、学号进行访问,并调用eat( )和study( )方法。
-
Person类
public class Person {public String name; //姓名public int age; //年龄public void eat(){System.out.println("吃饭");}}
-
Student类
public class Student extends Person {public String stuCode; //学号public void study(){System.out.println("学习Java程序设计");}}
-
测试类
public class TestStudent {@Testpublic void test(){Student stu = new Student();//赋值stu.name = "张三";stu.age = 20;stu.stuCode = "20230101";//访问System.out.println(stu.name);System.out.println(stu.age);System.out.println(stu.stuCode);//访问方法stu.eat();stu.study();}}
1.4. 练习
定义一个汽车类(Car),定义成员变量汽车品牌(String brand)、价格(double price),成员变量都是public修饰;定义成员方法drive( ),在其中输出“张三开着大众牌(brand值)汽车,价格是10(price值)万”,成员方法用public修饰。
定义一个电动汽车(ElectricCar),它继承Car类,定义成员变量电池容量(String batterySize),成员变量用public修饰;定义成员方法charge( ),在其中输出“给电动汽车充电”。
编写程序,使用无参构造方法实现ElectricCar类的实例化,对成员变量汽车品牌、价格、电池容量进行访问,调用drive( )和charge( )成员方法。
1.5. 思考
自定义一个父类,定义其成员变量(为子类抽取公有属性),成员变量都是public修饰;定义成员方法(为子类公有的方法),成员方法用public修饰。
自定义一个子类,它继承父类,定义子类特有的成员变量,成员变量用public修饰;定义子类成员方法(为子类特有)。
编写程序,使用无参构造方法实现子类的实例化,访问所有成员变量,并调用所有成员方法。
1.6. 继承的注意事项
(1)在Java中,类只支持单继承,不允许多继承。也就是说一个类只能有一个直接父类。
public class A{
}
public class B{
}
public class C extends A,B{ // C类不可以同时继承A类和B类
}
(2)在Java中,多层继承也是可以的,即一个类的父类可以再继承另外的父类。例如,C类继承自B类,而B类又可以继承自类A,这时,C类也可称作A类的子类。
public class A{
}
public class B extends A{ // 类B继承类A,类B是类A的子类
}
public class C extends B{ // 类C继承类B,类C是类B的子类,同时也是类A的子类
}
1.7. 方法的重写
(1)概念
在继承关系中,子类会自动继承父类中定义的方法,但有时在子类中需要对继承的方法进行一些修改,即对父类的方法进行重写。在子类中重写的方法需要和父类被重写的方法具有相同的方法名、参数列表以及返回值类型。
注意:子类重写父类方法时,不能使用比父类中被重写的方法更严格的访问权限。例如,父类中的方法是public权限,子类的方法就不能是private权限。如果子类在重写父类方法时定义的权限缩小,则在编译时将出现错误。
(2)案例
定义一个人类(Person),定义成员变量姓名(String name)和年龄(int age),成员变量都是private修饰,分别为这两个成员变量定义访问方法(getter)和修改方法(setter);定义成员方法hello( ),在其中输出“我的姓名是张三,我的年龄是20”,成员方法用public修饰。
定义一个学生类(Student),它继承Person类,定义成员变量班级(String className),成员变量用private修饰;重写父类成员方法hello( ),在其中输出“我的姓名是张三(name值),我的年龄是20(age值),我的班级是Java一班(className值)”,成员方法用public修饰。
编写程序,使用无参构造方法实现Student类的实例化,通过修改方法(setter)对成员变量赋值,调用访问方法(getter)输出变量值,并调用hello( )方法。
-
Person类
public class Person {private String name;private int age;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;}public void hello(){System.out.println("我的名字是:" + this.name+"我的年龄是:" +this.age);}
}
-
Student类
public class Student extends Person{private String className;public String getClassName() {return className;}public void setClassName(String className) {this.className = className;}@Overridepublic void hello() {super.hello();System.out.println("我的班级是:" + this.className);}
}
-
测试类
public class TestStudent {@Testpublic void test(){//实例化对象(无参构造方法)Student stu = new Student();//成员变量赋值stu.setName("张三");stu.setAge(20);stu.setClassName("Java一班");//输出成员变量值System.out.println(stu.getName());System.out.println(stu.getAge());System.out.println(stu.getClassName());//成员方法调用stu.hello();}}
1.8. super关键字
当子类重写父类的方法后,子类对象将无法访问父类中被子类重写过的方法。为了解决这个问题,Java提供了super关键字,使用super关键字可以在子类中访问父类的非私有方法、非私有属性以及构造方法。下面详细讲解super关键字的具体用法。
(1)使用super关键字访问或调用父类的非私属性或非私有方法,具体格式如下。
super.属性
super.方法(参数1,参数2…)
(2)使用super关键字调用父类中指定的构造方法,具体格式如下。
super(参数1,参数2…)
(3)super和this关键字的区别
super与this关键字的作用非常相似,都可以调用构造方法、方法和属性,但是两者之间还是有区别的,super与this的区别如下表所示。
区别点 | super | this |
访问属性 | 直接访问父类中的非私有属性 | 访问本类中的属性。如果本类中没有该属性,则从父类中继续查找 |
调用方法 | 直接调用父类中的非私有方法 | 调用本类中的方法。如果本类中没有该方法,则从父类中继续查找 |
调用构造方法 | 调用父类构造方法,必须放在子类构造方法的首行 | 调用本类构造方法,必须放在构造方法的首行 |