java学习笔记169-186 多态,抽象类,接口

前言
b站java课程学习笔记整理。
b站视频: 黑马程序员全套Java教程_Java基础入门视频教程,零基础小白自学Java必备教程
169. 多态
指的是同一个对象在不同情况下表现出来的不同形态。
我们可以说Kitty是猫的一种,也可以说Kitty是动物的一种。
多态的前提和实现
- 有继承/实现关系
- 有方法的重写
- 有父类引用指向子类的对象(
动物 animal = new 猫()
)
package 多态;
public class Animal {
public void eat(){
System.out.println("动物吃东西");
}
}
package 多态;
public class Cat extends Animal{
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
package 多态;
public class test {
public static void main(String[] args) {
Animal A = new Cat();
A.eat();
}
}
总结: 多态就是父类 对象=new 子类;
170. 多态中的成员访问特点
- 通过多态的形式访问成员变量,编译和运行要看左边。
- 通过多态的形式访问成员方法,编译看左边(父类中要有这个方法),运行看右边(运行的是子类中重写的方法)。
171. 多态的好处和弊端
-
好处:多态可以提高程序的拓展性,定义方法时,使用父类定义,具体执行时使用子类的重写方法执行。
-
弊端:多态不能调用子类特有的方法。
- 总结: 多态说白了就是调用父类旗下的很多子类时,一个一个添加太麻烦了,可以直接整合调用父类。
代码:
package 多态;
public class Animal {
public void eat(){
System.out.println("动物吃东西");
}
}
package 多态;
public class Cat extends Animal{
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
package 多态;
public class Dog extends Animal{
@Override
public void eat(){
System.out.println("狗吃肉");
}
public void security(){
System.out.println("狗能看门");
}
}
package 多态;
public class AnimalOperator {
public void operate(Animal a){
a.eat();
}
}
package 多态;
public class test {
public static void main(String[] args) {
Cat c = new Cat();
c.eat();
Dog d = new Dog();
d.eat();
AnimalOperator ao = new AnimalOperator();
ao.operate(c);
ao.operate(d);
// ao.security(d); 无法调用父类没有的,子类特有功能。
}
}
172. 多态中的转型
转型可以实现使用子类中的特有功能。转型分为向上转型(父类引用指向子类对象)和向下转型(父类引用强转为子类对象)。
代码:
package 多态强转;
public class Animal {
public void eat(){
System.out.println("动物吃东西");
}
}
package 多态强转;
public class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃鱼");
}
public void play(){
System.out.println("猫玩玩具");
}
}
package 多态强转;
public class test {
public static void main(String[] args) {
// 向上转型
Animal a = new Cat();
a.eat();
// 不可以 a.play(); 因为这是猫类特有。
// 向下转型
Cat c = (Cat)a;
c.eat();
c.play();
}
}
173. 多态转型的内存图
关键就是向下转型时要做一步判断。
174. 猫和狗
案例:猫和狗,需求使用多态的思想实现猫和狗。
- 定义动物类,包括成员变量(名字,年龄)、成员方法(getset,吃饭())、构造方法(无参、带参)。
- 定义猫类,包括成员方法(重写吃饭())、构造方法(无参、带参)。
- 定义狗类,包括成员方法(重写吃饭())、构造方法(无参、带参)。
- 定义测试类。
package 猫与狗多态;
public class Animal {
private String name;
private String age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public Animal() {
}
public Animal(String name, String age) {
this.name = name;
this.age = age;
}
public void eat(){
System.out.println("动物吃饭");
}
public void show() {
System.out.println(name + "," + age);
}
}
package 猫与狗多态;
public class Cat extends Animal{
public Cat(){}
public Cat(String name, String age){
super(name, age);
}
@Override
public void eat(){
System.out.println("猫吃鱼");
}
public void play(){
System.out.println("猫玩玩具");
}
}
package 猫与狗多态;
public class Dog extends Animal{
public Dog(){}
public Dog(String name, String age){
super(name, age);
}
@Override
public void eat(){
System.out.println("狗吃肉");
}
}
package 猫与狗多态;
public class Test {
public static void main(String[] args) {
Animal a = new Cat();
a.setAge("21");
a.setName("加菲");
a.show(); //先看cat,发现没有show,就去父类中继承了show。
a.eat();
System.out.println("----------------------------");
Animal b = new Cat("加菲", "10");
b.show();
b.eat();
Cat c = (Cat) b;
c.play();
System.out.println("----------------------------");
Animal d = new Dog("加菲", "10");
d.show();
d.eat();
}
}
总结:继承版猫与狗时提取共性,多态版猫和狗是对一个大类的重写整合。
175. 抽象类
动物不应该作为一个可以被创建对象的类!因为动物就是一个抽象的概念!
一个没有方法体的方法被定义为抽象方法,类被定义为抽象类。
176. 抽象类特点
- 抽象类和抽象方法要用
abstract
关键字来修饰。 - 抽象类里是可以有非抽象方法的。但是也可以没有抽象方法(但是没什么意义)。
- 类里有抽象方法,类一定是抽象类。
- 抽象类无法常规创建对象。抽象类会参照多态的方式创建对象。即先定义一个类继承,然后正常重写方法。
- 抽象类的子类要么重写继承所有的抽象方法,要么定义为抽象子类。
177. 抽象类的成员特点
-
抽象类可以有成员变量(变量或者常量)和非抽象成员方法。
-
抽象类可以有构造方法(用于多态时子类访问父类时初始化),这个构造方法不是创建对象用的。
178. 猫与狗(抽象类版)
- 定义动物类,姓名年龄,无参带参构造,getset方法,抽象eat()方法。
- 定义Cat类,继承,无参带参,重写吃饭
- 定义Dog类,继承,无参带参,重写吃饭
package 猫和狗抽象类;
public abstract class Animal {
private String name;
private String age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public Animal() {
}
;
public Animal(String name, String age) {
this.age = age;
this.name = name;
}
;
public abstract void eat();
public void show() {
System.out.println(name + "," + age);
}
}
package 猫和狗抽象类;
public class Cat extends Animal {
public Cat() {
}
public Cat(String name, String age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
package 猫和狗抽象类;
public class Dog extends Animal {
public Dog() {
}
public Dog(String name, String age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("狗吃肉");
}
}
package 猫和狗抽象类;
public class test {
public static void main(String[] args) {
Animal a = new Cat();
a.setAge("11");
a.setName("Kitty");
a.eat();
a.show();
Animal b = new Dog("Dogge","19");
b.eat();
b.show();
}
}
总结:就是在猫和狗多态版的基础上,去除了Animal
可以实体化的特性,将Animal
变成了一个抽象的“定义”。
179. 接口
接口是一种公共的规范标准。只要符合标准,大家都可以用。Java中的接口更多的体现在对行为的抽象。
180. 接口的特点
- 接口关键字用
interface
修饰。 - 类实现接口用
implements
表示。 - 接口不能实例化,要参照多态的方式使用子类实例化。
- 多态的形式:具体类多态,抽象类多态,接口类多态。
- 接口的实现类:要么重写抽象方法,要么是抽象类。
181. 接口的成员特点
- 接口中的成员变量默认被
public static final
修饰。所以接口中默认都是常量。 - 接口里没有构造方法(所有的子类默认访问的都是
object
无参构造) - 接口里不能有非抽象成员方法。
- 在接口里的方法默认带了
public abstract
前缀。182. 猫和狗接口版
案例:对猫和狗训练,实现跳高功能。
- 定义接口,跳高。
- 定义动物类,姓名年龄,无参带参构造,getset方法,抽象eat()方法。
- 定义Cat类,继承,无参带参,重写吃饭,跳高
- 定义Dog类,继承,无参带参,重写吃饭,跳高 代码只写了个猫的,以猫为例。 ```java package 猫和狗接口;
public abstract class Animal { private String name; private String age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public Animal(String name, String age) {
this.name = name;
this.age = age;
}
public Animal() {
}
public abstract void eat();
public void show() {
System.out.println(name + "," + age);
} }
```java
package 猫和狗接口;
public class Cat extends Animal implements Jumpping{
public Cat(){}
public Cat(String name,String age){
super(name, age);
};
@Override
public void eat() {
System.out.println("猫吃鱼");
}
@Override
public void jump() {
System.out.println("猫跳高");
}
}
package 猫和狗接口;
public interface Jumpping {
public abstract void jump();
}
package 猫和狗接口;
public class test {
public static void main(String[] args) {
// 动物的只能调动物方法
Animal a = new Cat("Kitty","23");
a.show();
a.eat();
// 因为Cat类里面有接口类,所以要想实现只能强转。
((Cat)a).jump();
// 接口的只能调接口方法
Jumpping j = new Cat("Doppy","21");
j.jump();
// 一般用这个
Cat c = new Cat("James","18");
c.show();
c.eat();
c.jump();
}
}
183. 类和接口的关系
- 类和类的关系:继承关系,只能一对一继承,但是可以多层继承。
- 类和接口的关系: 可以实现多个接口。甚至可以在继承一个类的时候实现接口。(
extends x implements inter1,inter2,inter3
) - 接口与接口的关系:可以单继承,也可以多继承。 (
extends x,y,z
)184. 抽象类和接口的区别
将类所具有的本身的功能设计为抽象类,将一些外部功能设计为接口。
抽象类是对事物的抽象,接口是对行为的抽象。
185.运动员和教练:案例分析
现在有乒乓球运动员和篮球运动员,乒乓球教练和篮球教练,跟乒乓球相关的需要学习英语。试着做出代码设计。
抽象类:人类:运动员、教练。
子类:乒乓球教练、篮球教练。
接口:学英语。
最后写测试类测试。
注意:谁不抽象,谁重写。
package 运动员与教练接口;
public interface English {
public abstract void speakEnglish();
}
package 运动员与教练接口;
public abstract class Human {
private String name;
private String age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public Human(String name, String age) {
this.name = name;
this.age = age;
}
public Human(){}
public abstract void eat();
public void show(){
System.out.println("姓名"+name+"年龄"+age);
}
}
package 运动员与教练接口;
public abstract class Coach extends Human {
Coach(){}
Coach(String name, String age){
super(name, age);
}
public abstract void teach();
}
package 运动员与教练接口;
public abstract class Sportsman extends Human {
public Sportsman() {
}
public Sportsman(String name, String age) {
super(name, age);
}
public abstract void study();
}
package 运动员与教练接口;
public class BBCoach extends Coach{
public BBCoach() {
}
public BBCoach(String name, String age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("篮球教练吃饭");
}
@Override
public void teach() {
System.out.println("篮球教练教篮球");
}
}
package 运动员与教练接口;
public class BBSportsman extends Sportsman {
public BBSportsman() {
}
public BBSportsman(String name, String age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("篮球运动员吃饭");
}
@Override
public void study() {
System.out.println("篮球运动员学习打篮球");
}
}
package 运动员与教练接口;
public class TTCoach extends Coach implements English{
public TTCoach() {
}
public TTCoach(String name, String age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("乒乓球教练吃饭");
}
@Override
public void teach() {
System.out.println("乒乓球教练教乒乓球");
}
@Override
public void speakEnglish() {
System.out.println("乒乓球教练需要学习英语");
}
}
package 运动员与教练接口;
public class TTSportsman extends Sportsman implements English{
public TTSportsman() {
}
public TTSportsman(String name, String age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("乒乓球运动员吃饭");
}
@Override
public void study() {
System.out.println("乒乓球运动员学乒乓球");
}
@Override
public void speakEnglish() {
System.out.println("乒乓球运动员学英语");
}
}
package 运动员与教练接口;
public class test {
public static void main(String[] args) {
BBSportsman bbs = new BBSportsman("James","21");
bbs.show();
bbs.eat();
bbs.study();
System.out.println("----------------------------");
TTSportsman tts = new TTSportsman();
tts.setAge("19");
tts.setName("Long Ma");
tts.show();
tts.eat();
tts.study();
tts.speakEnglish();
System.out.println("----------------------------");
BBCoach bbc = new BBCoach("Popovich","80");
bbc.show();
bbc.eat();
bbc.teach();
System.out.println("----------------------------");
TTCoach ttc = new TTCoach("Guoliang Liu","45");
ttc.show();
ttc.eat();
ttc.teach();
ttc.speakEnglish();
}
}