day01 【继承、抽象类、综合案例】
今日内容介绍
继承及其特点
this/super
方法重写
抽象类
开题 复习
0.1 定义一个类
public class 类名{
//成员变量
//成员方法
}
注意:类名约定俗称写的英文,but首字母是大写的,后面每个单词的首字母要大写。一定要遵循。
举例:
public class Dog{
String name;
int age;
//成员方法
public void eat(){
System.out.println("狗吃狗粮~");
}
}
0.2 通过类创建对象
类是模拟事务的一种形象,它是抽象的,需要创建对象来进行具体体现。
格式:
数据类型 对象名 = new 类名();
比如 创建dog
Dog dog = new Dog();
调用方法
dog.eat();
调用属性
dog.name="小白";
0.3 封装
成员变量加了private.隐藏成员变量,外界无法直接访问。
先要赋值就要提供 setXxx方法,想要获取提供getXxx()。
变量的访问有个原则:就近原则。
public class Dog{
private String name;
private int age;
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
...
//成员方法
public void eat(){
System.out.println("狗吃狗粮~");
}
}
this关键字有什么用:
区分了成员变量和局部变量。
this含义:
代表 谁调用就是谁。
0.4 构造方法
构造方法的作用:
初始化对象的,主要是初始化对象中的成员变量。
构造方法的特点:
方法名和类名是一样的;
没有返回值,连void的没有。
构造方法注意事项:
a:如果不写 系统会提供一个默认的无参构造。
b: 如果写了构造,默认就没了。
c: 建议写 无参和满参
public class Dog{
private String name;
private int age;
public Dog(){}
public Dog(String name,int age){
this.name = name;
this.age = age;
}
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
...
//成员方法
public void eat(){
System.out.println("狗吃狗粮~");
}
}
0.5 this
this: 关键字
用于区分成员变量和局部变量,代表当前的对象。
谁调用这个方法,这个方法中的this就是谁。
0.6 private
可以修饰成员方法
可以修饰成员变量
可以修饰构造方法
提供公共的访问方式。
第一章 继承
1.1 继承的概念【重点】
假如我们要定义如下类: 讲师类,班主任类和就业指导类,分析如下:
1. 讲师类 属性:姓名,年龄,工资 行为:展示信息,讲课
2. 班主任类 属性:姓名,年龄,工资 行为:展示信息,管理班级
3. 就业指导类 属性:姓名,年龄,工资 行为:吃饭,展示信息,辅导就业
如果我们定义三个类,每个类都有姓名,年龄,工资,展示信息,代码重复了,需要把重复的代码单独定义到一个类中
在一个已知类A的基础上,创建新类B的过程,称之为继承
这里类A,称为父类,基类,超类
这里类B,称为子类,派生类
1.继承的概念:
向上抽取,把相同的内容定义在父类中,子类完成继承,子类继承父类,就自动拥有了父类的属性和方法。
2.什么情况下使用继承(不能随便继承)?
符合 is a 的关系
xxx 是 yyy 的一种
学生是人的一种 老师也是人的一种
3.继承的好处
提高代码复用性
提高代码维护性
让类和类之间产生关系,学习多态的前提。
继承的弊端:
1.2 继承的格式和代码体现【重点】
格式:
先定义父类
public class Fu{
}
再定义子类
public class Zi extends Fu{}
特点:
子类自动拥有父类的属性和方法,
A:Fu被称为父类 Zi被称为子类。
B:子类对象可以使用父类中除了私有以外的所有属性和方法。
代码体现
先父类 后子类 然后来个测试类
父类
public class Employee {
String name;
int age;
int salary;
public void show(){
System.out.println("姓名:"+name+",年龄:"+age+",工资:"+salary);
}
}
讲师类
package com.itheima.extends01;
/*
老师继承员工类 怎么做
讲师
有什么功能 讲课
*/
public class Teacher extends Employee{
public void teaching(){
System.out.println("老师正在讲解面向对象");
}
}
班主任类
package com.itheima.extends01;
/*
班主任类
继承员工
特殊功能 管理班级
*/
public class Manager extends Employee{
//特有功能 管理班级
public void manageClass(){
System.out.println("班主任正在管理班级");
}
}
如何使用:测试类测试
package com.itheima.extends01;
public class Demo {
public static void main(String[] args) {
//创建讲师对象
Teacher teacher = new Teacher();
//如何给成员变量赋值呢?
teacher.name = "法外狂徒张三";
teacher.age=22;
teacher.salary=10000;
//调用方法
teacher.show();//调用父类方法
teacher.teaching();//调用子类特有方法
// 自己测试一个班主任类
}
}
总结
一旦子类继承了父类,就自动拥有了父类的成员属性和成员方法,可以直接调用。
还可以直接调用自己的功能。
1.3 java 继承的特点
java 只支持单继承,不支持多继承,但是可以多层继承。
1.4 在继承关系中 成员变量的访问特点 (重点是记住结论)
1.4.1 子类中定义的成员变量和父类中定义的成员变量 名字不一样
package com.itheima.extends02;
//父类
public class Fu {
int num1 = 10000;
}
package com.itheima.extends02;
//子类
public class Zi extends Fu {
int num2 = 10;
public void show(){
//子类在自己方法中能否使用自己的成员变量
System.out.println(num2);
// 子类自己没有 可以访问父类的成员变量
System.out.println(num1);
}
}
package com.itheima.extends02;
//测试类
public class Demo {
public static void main(String[] args) {
//创建子类对象
Zi zi = new Zi();
zi.show();
//能不能直接方法
System.out.println("访问子的num2:"+zi.num2);
System.out.println("访问父定义的num1:"+zi.num1);
}
}
成员属性访问特点:
子类自己有用自己的。
子类没有呢,找父类。
注意 子类能找父类的 父类找不到子类的。
1.4.2 子类中定义的成员变量和父类中定义成员变量 名字一样的
基于上面案例进行修改 父类中定义一个属性叫 num 子类中定义一个属性叫 num 甚至在成员方法中定义一个属性叫 num.
package com.itheima.extends03;
//父类
public class Fu {
//在父类中定义一个成员变量num值是100
int num = 100;
}
package com.itheima.extends03;
//子类
public class Zi extends Fu{
//在子类中定义一个成员变量num值是200
int num = 200;
//普通方法
public void show(){
//在局部位置--方法中
// 在方法中创建一个 属性叫num 值是300
int num = 300;
System.out.println(num);//遵循就近原则 结果是300
// 访问本类中的成员变量
System.out.println(this.num);
// 访问父类中的成员变量
System.out.println(super.num);
}
}
package com.itheima.extends03;
public class Demo {
public static void main(String[] args) {
//创建子类对象
Zi zi = new Zi();
//调用show方法
zi.show();
}
}
成员属性访问特点:
子类自己有用自己的。
子类没有呢,找父类。
注意 子类能找父类的 父类找不到子类的。
子类中变量访问特点遵循就近原则!
先从 方法内部找,方法内部有就使用。
如果没有,就从本类的成员位置找,有就使用。
如果没有,就去父类的成员位置找,有就使用,如果没有 继续往上....
问题:如果在局部位置我就想访问成员变量怎么玩?通过 this 关键字,访问本类中的成员。
问题:如果在局部位置我就想访问父类成员变量怎么玩?通过 super 关键字,访问父类中的成员。
1.5 在继承关系中 成员方法的访问特点
如果成员方法不一样 如果成员方法名一样
package com.itheima.extends04;
public class Fu {
public void methodFu(){
System.out.println("父类中的methodFu方法 ");
}
public void method(){
System.out.println("父类中的 method方法");
}
public void driver(){
System.out.println("开着桑塔纳,摇摇晃晃去东北。");
}
}
package com.itheima.extends04;
public class Zi extends Fu{
public void methodZi(){
System.out.println("子类的方法");
}
public void method(){
System.out.println("子类的方法 method");
}
public void driver(){
System.out.println("开着五菱宏光,直角飘逸。");
}
}
package com.itheima.extends04;
public class Demo {
public static void main(String[] args) {
//创建子类对象
Zi zi = new Zi();
zi.methodZi();//可以调用自己的方法
zi.methodFu();//可以调用父类的方法
//
System.out.println("猜一猜 zi.method()结果是什么?");
zi.method();
zi.driver();
}
}
结论:子类没有调用父类的,有调用自己的。如果出现了同名,优先使用子类的方法。
1.6 方法重写 (重点是可以实现)
什么叫方法重写:
在子类中出现了与父类一模一样的方法(返回值类型,方法名和参数列表一样),
会出现覆盖效果,也被称为重写或者复写。 Override 重写
怎么实现方法重写?
在子类中定义一个一模一样方法(返回值类型,方法名和参数列表)
怎么检验它是方法重写呢
jdk8 jar 包中,@Override 的注解可以进行检验。
跟方法重载不是一回事
什么是方法重载,在同一个类中,方法名称相同,参数列表不同。被称为方法的重载。
方法重载:调用方便。
快捷方式做方法重载
ctrl+o
方法重写的好处:沿袭了父类中的功能,又进行了增强。
方法重写注意事项:
父类中私有方法不能被重写。
子类重写的方法访问权限必须大于等于父类方法的权限。
public>protected>默认(default)>private
子类重写方法时一定保证,方法名 参数列表 返回值要一模一样。
1.7 手机案例---重写
OldPhone
package com.itheima.extends05Phone;
/*
定义老款手机类
成员方法 三个
打电话
发短信
显示来电
*/
public class OldPhone {
//打电话
public void call(String who){
System.out.println("正在给:"+who+"打电话....");
}
//发短信
public void sendMessage(String who,String msg){
System.out.println("给"+who+"发"+msg);
}
//来电显示
public void show(){
System.out.println("反诈中心110来电!!");
}
}
NewPhone
package com.itheima.extends05Phone;
/*
新款手机继承老款手机
*/
public class NewPhone extends OldPhone {
//发短信打电话 不需要重写
// 来电显示需要重写
@Override
public void show() {
super.show();// 调用父类中已经实现的代码
// System.out.println("反诈中心110来电!!");
//显示头像 显示位置
System.out.println("哥们 你头像是个绿色的");
System.out.println("哥们 你的位置在北京昌平");
}
}
Demo
package com.itheima.extends05Phone;
public class Demo {
public static void main(String[] args) {
//测试老款手机
OldPhone oldPhone = new OldPhone();
oldPhone.call("响哥");
oldPhone.sendMessage("博文","响哥想你了");
oldPhone.show();
//测试新款手机
NewPhone newPhone = new NewPhone();
newPhone.call("马保国");//执行的父类中定义好的
newPhone.sendMessage("马大师","我要学习混元形意太极拳");//执行父类中定义好的
newPhone.show();//执行重写后的
}
}
第二章 继承中 构造的访问特点
2.1 父类构造对子类的意义
子类能继承父类的构造吗?
不能!!
构造方法的名字跟类名是一致的,语法上来说 子类是无法继承父类构造的。
package com.itheima.extends06;
public class Fu {
int num;
public Fu(){
System.out.println("父 空参....");
}
public Fu(int num){
System.out.println("父 带参构造");
this.num=num;
}
}
package com.itheima.extends06;
public class Zi extends Fu{
public Zi(){
System.out.println("子 空参构造");
}
public Zi(int num){
System.out.println("子 带参构造");
}
}
package com.itheima.extends06;
public class Demo {
public static void main(String[] args) {
//创建一个子类对象
Zi zi = new Zi();
System.out.println("----------------");
//创建一个子类对象 使用带参构造
Zi zi1 = new Zi(10);
}
}
我们通过写代码,观察发现。子类在构建对象的时候,都会默认调用父类的空参构造!
系统会默认给子类构造的第一行加上 super():代表初始化子类之前先初始化父类。
我们如果手动给出 super(..)语法,子类还会调用父类空参构造吗?不会。
我们做了一件事情,我们把父类中空参构造删掉。对子类有什么影响
为什么 在 public Zi()这里爆红?
因为我们不写 super(..)默认第一行是 super() 调用的父类的空参构造。
现在父类没有空参构造,不报错报什么?肯定报错。
如果报错,手动写一个调用存在的父类构造即可。
或者试用 this 语句调用本类中的构造,本类构造手动调用父类的带参构造(了解 因为我们不这样写。)
注意 this(..)super(..)都是作用于第一行 不能共存。
2.2 子类初始化的内存图
代码体现
Perosn 类
package com.itheima.extends07neicun;
public class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = 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 show(){
System.out.println("name:"+name+" ...age:"+age);
}
}
Student 类
package com.itheima.extends07neicun;
public class Student extends Person {
private int score;//成绩
public Student(){}
public Student(String name, int age, int score) {
super(name, age);//把name age属性值 给父类中的成员
this.score = score;//把score给了本类中的成员
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
}
测试类
package com.itheima.extends07neicun;
public class Demo {
public static void main(String[] args) {
Student student = new Student("力宏", 45, 100);
System.out.println("------");
}
}
子类中有成员变量,父类中也有成员变量
那么构建子类对象的时候,是先加载父类成员,还是子类成员变量。
父类。能不能以内存的形式来讲解!可以 ,那么属性什么时候被加载,加载顺序是什么样的,看 ppt 内存图。
通过内存图
强调一点 this 当前类对象的引用。super 是父类空间的标识(可以理解为是父类对象的引用).
第三章 抽象类
3.1 纵向提取思想的应用
假设有两个类 一个类是 猫 一个类是 狗
抽象:
概念:说不清的,不具体的。功能要有,但是不给具体的实现。这种方法被称为抽象方法。
格式:
public abstract 返回值类型 方法名();
什么是抽象类:在一个类中如果有抽象方法,那么这个类就必须是抽象类。
public abstract class 类名{}
抽象类中抽象方法存在意义
强制要求子类具备该功能,必须要实现该方法。
3.2 猫狗案例
Animal.java
package com.itheima.abstract01;
public abstract class Animal {
//动物具备吃的功能但是 不能给出具体吃什么 所以吃的方法是抽象的方法
public abstract void eat();
// 动物具备喝水的功能
public void drink(){
System.out.println("喝水");
}
}
Cat.java
package com.itheima.abstract01;
/*
Cat类继承了一个抽象类 Animal
爆红 为甚呢?
猫继承了动物,猫就具备了吃的功能
猫是不是一个具体的动物
应该具备 具体吃的功能呢
必须要把 吃的方法实现
*/
public class Cat extends Animal{
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
Dog.java
package com.itheima.abstract01;
/*
狗继承动物 也要重写 吃的方法
*/
public class Dog extends Animal{
@Override
public void eat() {
System.out.println("狗啃骨头");
}
}
Demo.java
package com.itheima.abstract01;
public class Demo {
public static void main(String[] args) {
//创建狗对象 吃吃喝喝
Dog dog = new Dog();
dog.eat();
dog.drink();
// 创建猫对象 吃吃 喝喝
Cat c = new Cat();
c.eat();
c.drink();
}
}
3.3 抽象类注意事项
- 抽象类不能创建对象,如果创建,编译报错。通过子类对象。
- 抽象类有构造,不能创建对象的原因,因为里面有抽象方法。避免调用的尴尬。
- 抽象类构造的意义,就是提供给子类创建对象的时候,初始化父类成员。
- 抽象类中可以没有抽象方法,但是抽象方法必须在抽象类中。抽象类中可以有 0-n 个抽象方法。
- 抽象类的子类
- 可以是重写抽象方法的子类。
- 还可以是 没有重写方法的抽象类。
第四章 综合案例
步骤
1:创建工程师类
属性 工号 id 姓名 name
setget方法
空参和满参
抽象方法 工作
2:创建 抽象类 研发工程师 以及 维护工程师
产生继承关系
空参和满参构造
不用实现
3:javaee工程师 android工程师 网络维护工程师 硬件维护工程师
产生继承关系
空参和满参构造
工作要实现,因为是具体的类。
4:随便找一个具体类实现。
工程师类
package com.itheima.demo;
/*
创建工程师类
抽象类
*/
public abstract class GongChengShi {
//属性
private int id;
private String name;
//空参满参
public GongChengShi() {
}
public GongChengShi(int id, String name) {
this.id = id;
this.name = name;
}
//set get方法
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//抽象的工作方法
public abstract void work();
}
研发工程师类
package com.itheima.demo;
//研发工程师继承 工程师
public abstract class YanFa extends GongChengShi{
//写空参满参
public YanFa() {
}
//作用是传递参数给父亲的成员变量
public YanFa(int id, String name) {
super(id, name);
}
}
维护工程师类
package com.itheima.demo;
//维护工程师继承 工程师
public abstract class WeiHu extends GongChengShi{
//写空参满参
public WeiHu() {
}
//作用是传递参数给父亲的成员变量
public WeiHu(int id, String name) {
super(id, name);
}
}
javaee 工程师类
package com.itheima.demo;
//javaEE工程师继承研发 要重写 因为是具体类
public class JavaEE extends YanFa{
// 需要空参满参
public JavaEE() {
}
public JavaEE(int id, String name) {
super(id, name);
}
@Override
public void work() {
System.out.println("员工号:"+getId()+"名字为:"+getName()+"正在研发淘宝网站");
}
}
Android 工程师类
package com.itheima.demo;
//Android工程师继承研发 要重写 因为是具体类
public class Android extends YanFa{
// 需要空参满参
public Android() {
}
public Android(int id, String name) {
super(id, name);
}
@Override
public void work() {
System.out.println("员工号:"+getId()+"名字为:"+getName()+"正在研发淘宝APP端");
}
}
网络维护工程师类
package com.itheima.demo;
//WangLuo工程师继承维护部 要重写 因为是具体类
public class WangLuo extends WeiHu{
// 需要空参满参
public WangLuo() {
}
public WangLuo(int id, String name) {
super(id, name);
}
@Override
public void work() {
System.out.println("员工号:"+getId()+"名字为:"+getName()+"正在进行网络的维护");
}
}
硬件维护工程师类
package com.itheima.demo;
//YingJian工程师继承维护部 要重写 因为是具体类
public class YingJian extends WeiHu{
// 需要空参满参
public YingJian() {
}
public YingJian(int id, String name) {
super(id, name);
}
@Override
public void work() {
System.out.println("员工号:"+getId()+"名字为:"+getName()+"正在进行修理打印机");
}
}
测试类
package com.itheima.demo;
public class Demo {
public static void main(String[] args) {
//创建一个JavaEE工程师
JavaEE ee = new JavaEE(9527, "华安");
ee.work();
}
}