二、面向对象--3
(一)继承思想
144、引出继承关系
//老师
class Teacher
{
String name;
int age;
String level; //级别
public void sleep(){} //定义一个sleep()方法
}
//学生
class Student
{
String name;
int age;
String sn; //学号
public void sleep(){}
}
//学生
class Employee
{
String name;
int age;
String hireDate; //入职时间
public void sleep(){}
}
父类:存放的共性(共同的特性(状态/行为))
子类:存放的特性(自己特有的特性(状态/行为))
解决代码重复问题
145、理解继承思想
在Java语言中,存在多个类时,使用“extends”关键字来表示子类和父类之间的关系。类和类之间的继承关系,在Java中只能单继承,不允许多继承;但是允许多重继承
语法格式:
public class 子类类名 extends 父类类名
{
编写自己特有的状态和行为
}
//人类
class Person //被继承类 super class 父类/超类/基类/被拓展类
{
String name; //private修饰不能被继承
int age;
public void sleep(){}
//Person(){} //构造器不能被继承
}
//老师
class Teacher extends Person //sub class 子类/拓展类
{
String level; //级别
}
//学生
class Student extends Person
{
String sn; //学号
}
//学生
class Employee extends Person
{
String hireDate; //入职时间
}
public class ExtendsDemo2
{
public static void main(String[] args)
{
Student s = new Student(); //创建一个学生对象
System.out.println(s.name); //获取学生对象
System.out.println(s.sn);
}
}
在Java中除了Object类之外,每一个类都有一个直接的父类
Student 的直接父类是Person。问题:class Person{}; 此时Person的父类又是谁? class Person{}; 等价于class Person extends Object{};
Object类是Java语言的根类(任何类都是Object的子类)。Object类要么是一个直接父类,要么是一个类的间接父类。
继承关系的作用:1)解决代码的重复问题;2)表示出一个体系(真正的作用)
146、子类继承了父类的哪些成员
147、方法覆盖
//鸟类
class Bird
{
public void fly()
{
System.out.println("我在仰望,自由飞翔!");
}
}
//企鹅
class Penguin extends Bird
{
@override //判断当前子类的方法是否覆盖了父类的方法
public void fly() //重新定义了fly,子类中的fly就覆盖了父类中的fly;就是方法的覆盖/覆写Override
{
System.out.println("对不起,偶是折翼的天使!");
}
}
//方法覆盖
public class OverrideDemo
{
public static void main(String[] args)
{
//创建一个企鹅对象,并调用其飞翔的方法
Penguin p = new Penguin();
p.fly(); //先去子类中寻找fly方法,如果找到就执行,如果找不到,继续去父类中去找
}
}
148、方法重载和方法覆盖的区别
方法重载:Overload 解决了同一个类中,相同功能的方法名不同的问题,既然是相同的功能,那么方法的名字就应该相同,只有一个类。同类中,方法名相同,方法参数列表不同(参数类型,参数个数,参数顺序)
方法重写:Override 解决子类继承父类之后,可能父类的某一个方法不满足子类的具体特征,此时需要重新在子类中定义该方法,并并重写该方法体。父类和子类的方法签名相同,建议:直接拷贝父类中方法的定义到子类中,再重写方法体
批判:本身二者一点关系没有,仅仅只是因为名字很像
149、super关键字
this:当前对象,谁调用this所在方法,this就是哪一个对象
super:调用当前对象的父类对象
//鸟类
class Bird
{
public void fly()
{
System.out.println("我在仰望,自由飞翔!");
}
}
//企鹅
class Penguin extends Bird
{
//@override //判断当前子类的方法是否覆盖了父类的方法
public void fly() //重新定义了fly,子类中的fly就覆盖了父类中的fly;就是方法的覆盖/覆写Override
{
System.out.println("对不起,偶是折翼的天使!");
}
public void say()
{
//调用Bird类中的fly方法
System.out.println("我要歌唱......");
fly(); //调用的是自己所在类的方法,等价于 this.fly(); //对不起,偶是折翼的天使!
super.fly(); //调用的是父类的方法 //我在仰望,自由飞翔!
}
}
//在子类中的某一个方法中,去调用父类中被覆盖的方法
public class SuperDemo
{
public static void main(String[] args)
{
//创建一个企鹅对象,并调用其飞翔的方法
Penguin p = new Penguin();
p.say();
}
}
150、子类的初始化过程
子类的初始化过程:创建子类对象的过程(现有父类对象,而后才能有子类对象,必须先调用父类构造器,才能调用子类构造器)
在创建子类对象之前,会先创建父类对象。调用子类构造器之前,在子类构造器中会先调用父类的构造器,默认调用的是父类无参数构造器
1)如果父类不存在可以被子类访问的构造器,则不能存在子类
2)如果父类没有提供无参数构造器,此时子类必须显示通过super语句去调用父类带参数的构造器
//动物
class Animal
{
private String name;
private int age;
Animal(String x)
{
System.out.println("Animal构造器" + x);
}
}
//鱼
class Fish extends Animal
{
private String color; // 颜色
Fish()
{
//System.out.println("Fish构造器"); //错误: 对super的调用必须是构造器中的第一个语句
super("xxx"); //Animal构造器xxx
// 隐式super(); //调用父类无参数构造器
System.out.println("Fish构造器");
}
}
//子类的初始化过程:创建子类对象的过程
public class SuperInitDemo
{
public static void main(String[] args)
{
//创建鱼对象
Fish f = new Fish();
}
}
//动物
class Animal
{
private String name;
private int age;
Animal(String name, int age)
{
System.out.println("Animal构造器");
this.name = name;
this.age = age;
}
public String getName()
{
return name;
}
}
//鱼
class Fish extends Animal
{
private String color; // 颜色
Fish(String name, int age, String color)
{
super(name,age); //调用父类构造器 //调用父类构造器必须作为子类构造器的第一句话
this.color = color;
}
public void say()
{
System.out.println(super.getName() +" ,"+ this.color); //
}
}
//子类的初始化过程:创建子类对象的过程
public class SuperInitDemo
{
public static void main(String[] args)
{
//创建鱼对象
Fish f = new Fish("尼莫", 5, "橘黄色");
f.say();
}
}
151、super应用场景和各种隐藏现象
super关键字的使用场景:
1)使用super解决子类隐藏父类的字段,一般不讨论,因为破坏封装
class SuperClass
{
public String name = "superClass.name";
}
class SubClass extends SuperClass
{
public int name =18;
public void doWork()
{
System.out.println(super.name); //superClass.name
System.out.println(name); //18
}
}
2)在子类方法中调用父类被覆盖的方法,引出super的例子,此时必须使用super
3)在子类构造器中调用父类构造器。使用super语句:super([实参]);
static不能和super以及this共存
152、Object类和常用方法
Object类是Java语言的根类,要么是一个类的直接父类,要么就是一个类的间接父类
class ABC{}; 等价于class ABC extends Object{};
(二)多态思想
153、理解多态思想
继承关系是一种“is A”的关系,也就是说子类是父类的一种特殊情况
多态的特点:把子类对象赋给父类变量,在运行时期会表现出具体的子类特征。
//普通动物
class Animal
{
public void eat()
{
System.out.println("吃一般的食物");
}
}
//狗
class Dog extends Animal
{
public void eat()
{
System.out.println("吃肉骨头");
}
}
//猫
class Cat extends Animal
{
public void eat()
{
System.out.println("吃鱼");
}
}
//引出多态
class AnimalDemo
{
public static void main(String[] args)
{
Animal a = new Dog(); //创建一只狗对象
a.eat(); //吃肉骨头
a = new Cat(); //创建一只猫对象
a.eat(); //吃鱼
}
}
154、多态的好处
//普通动物
class Animal
{
public void eat()
{
System.out.println("吃一般的食物");
}
}
//狗
class Dog extends Animal
{
public void eat()
{
System.out.println("吃肉骨头");
}
}
//猫
class Cat extends Animal
{
public void eat()
{
System.out.println("吃鱼");
}
}
//饲养员
class Person
{
public void feed(Dog d) // 喂养狗的方法
{
System.out.println("feeding......");
d.eat();
}
public void feed(Cat c) // 喂养猫的方法
{
System.out.println("feeding......");
c.eat();
}
}
//引出多态
class AnimalDemo
{
public static void main(String[] args)
{
Person p = new Person(); //创建饲养员对象
Dog d = new Dog(); //创建一只狗对象
p.feed(d);
Cat c = new Cat(); //创建一只狗对象
p.feed(c);
}
}
//普通动物
class Animal
{
public void eat()
{
System.out.println("吃一般的食物");
}
}
//狗
class Dog extends Animal
{
public void eat()
{
System.out.println("吃肉骨头");
}
}
//猫
class Cat extends Animal
{
public void eat()
{
System.out.println("吃鱼");
}
}
//饲养员
class Person
{
public void feed(Animal a) // 调用Animal类型的参数
{
System.out.println("feeding......");
a.eat();
}
}
//引出多态
class AnimalDemo
{
public static void main(String[] args)
{
Person p = new Person(); //创建饲养员对象
Animal a = new Dog(); //创建一只狗对象
p.feed(a);
a = new Cat();
p.feed(a);
}
}
155、多态时方法的调用问题
前提:必须先存在多态情况 存在父类:SuperClass,子类:SubClass 方法doWork
156、引用类型转换和instance运算符
instanceof 运算符:判断该对象是否是某一个类的实例
语法格式:boolean b = 对象A instanceof 对象B //判断A对象是否是B对象的实例,如果是,返回true
若对象是类的实例返回true,是类的父类的实例也返回true
在开发中,有时候只想判断是真实类型的实例,而不想判断为编译类型的实例
//普通动物
class Animal
{
public void eat()
{
System.out.println("吃一般的食物");
}
}
//狗
class Dog extends Animal
{
public void eat()
{
System.out.println("吃肉骨头");
}
public void watch()
{
System.out.println("看门");
}
}
//猫
class Cat extends Animal
{
public void eat()
{
System.out.println("吃鱼");
}
public void catchMouse()
{
System.out.println("抓老鼠");
}
}
//饲养员
class Person
{
public void feed(Animal a) // 调用Animal类型的参数
{
System.out.println("feeding......");
a.eat();
if (a instanceof Dog) //如果a是Dog类型 (判断对象是否是某一个类的实例)
{
Dog d = (Dog)a; //将a强制转换成Dog类型
d.watch();
}else if(a instanceof Cat)
{
Cat c = (Cat)a;
c.catchMouse();
}
}
}
//instanceof运算符
class AnimalDemo1
{
public static void main(String[] args)
{
Person p = new Person(); //创建饲养员对象
Animal a = new Dog(); //创建一只狗对象
p.feed(a);
a = new Cat(); //创建一只狗对象
p.feed(a);
System.out.println("--------------------");
Object obj ="ABC"; //把String 类型对象赋给Object类型
System.out.println(obj instanceof Object); //true
System.out.println(obj instanceof String); //true
System.out.println(obj instanceof System); //false
System.out.println(obj.getClass()); //class java.lang.String (获取对象的真实类型)
System.out.println(obj.getClass() == String.class);//true
System.out.println(obj.getClass() == Object.class);//false
}
}
(三)组合关系
157、组合关系
继承关系:子类可以继承到父类中的部分成员,子类是可以修改到父类的信息。继承关系破坏封装
为什么引入继承?为了代码复用问题,不一定非要用继承,也可以使用包含关系(has A)
158、小结