目录
多态
- 多态的概述
- 多态的成员访问特点
- 多态的好处和弊端
- 向上转型和向下转型
- 多态内存图
抽象类
- 抽象类的概述
- 抽象类的成员特点
- 抽象类的案例
接口
- 接口的概述
- 接口的成员特点
- 类与类,类与接口,接口与接口的关系
- 抽象类与接口的区别
- 接口的案例
多态
多态:某一个事物,在不同时刻表现出来的不同状态。
举例:Cat c=new Cat();Animal a=new Cat();猫可以是猫的类型。猫 m = new 猫();
同时猫也是动物的一种,也可以把猫称为动物。动物 d = new 猫();
ps :( 多态中必须有继承关系,要有方法重写,也可以没有方法重写但这样的多态是没有意义的,要有父类应用指向子类对象)
代码演示
public class MyTest {
public static void main(String[] args) {
Cat cat = new Cat();
cat.eat();//我没有删除super.eat()所以就有二个吃饭内容
cat.play();
System.out.println("-----------------------");
Animal an = new Cat();//多态演示,要有父类引用指向子类对象
an.eat();
System.out.println("-----------------------");
Gog gog = new Gog();
gog.eat();
gog.seedoor();
System.out.println("--------------------------");
Gog an2= new Gog();//多态演示,要有父类引用指向子类对象
an2.eat();
}
}
class Animal{
public void eat(){
System.out.println("吃饭");
}
}
class Cat extends Animal{
@Override
public void eat() {
super.eat();
System.out.println("吃鱼");
}
public void play(){
System.out.println("抓老鼠");
}
}
class Gog extends Animal{
@Override
public void eat(){
System.out.println("吃骨头");
}
public void seedoor(){
System.out.println("看门");
}
}
如果采用了多态的这种方式,子类重写了父类的方法,那么我在用父类引用调用方法时,会以子类重写过后的为准
多态中成员访问特点
- 成员变量:编译看左边,运行看左边。
- 构造方法:创建子类对象的时候,会访问父类的构造方法,对父类的数据进行初始化。
- 成员方法:编译看左边,运行看右边。
- 静态方法:编译看左边,运行看左边。
ps:(静态和类相关,算不上重写,所以,访问还是左边的)
代码演示
public class MyTest2 {
public static void main(String[] args) {
Fu an = new Zi();
System.out.println(an.num);//多态的形式访问成员变量访问还是父类成员变量
an.show();//多态的形式调用方法,首先看这个方法父类里面有没有,如果没有就报错,有的话就访问子类方法
an.test();//多态的形式调用静态方法还是运行的是父类方法
Fu.test();
Zi.test();
}
}
class Fu{
int num=100;
public void show(){
System.out.println("fushow");
}
public static void test(){
System.out.println("futest");
}
}
class Zi extends Fu{
int num=120;
@Override
public void show() {
System.out.println("zishow");
}
public static void test(){
System.out.println("zitest");
}
}
多态的好处与弊端,以及弊端解决方法
- 提高了代码的维护性(继承保证)
- 提高了代码的扩展性(由多态保证)
- 弊端:不能访问子类的自有的方法(但可以通过向下转型可以访问)
代码演示向下转型
public class MyTest {
public static void main(String[] args) {
Cat cat = new Cat();
cat.eat();//我没有删除super.eat()所以就有二个吃饭内容
cat.play();
System.out.println("-----------------------");
Animal an = new Cat();//多态演示,要有父类引用指向子类对象
an.eat();
// an.play()直接访问会报错。通过向下转型就可以访问子类独有的方法
Cat cat1=(Cat) an ;//向下转型
cat.play();//这就可以访问
((Cat) an).play();//向下转型的另一种方式和上面一样
System.out.println("-----------------------");
Gog gog = new Gog();
gog.eat();
gog.seedoor();
System.out.println("--------------------------");
Gog an2= new Gog();//多态演示,要有父类引用指向子类对象
an2.eat();
}
}
class Animal{
public void eat(){
System.out.println("吃饭");
}
}
class Cat extends Animal{
@Override
public void eat() {
super.eat();
System.out.println("吃鱼");
}
public void play(){
System.out.println("抓老鼠");
}
}
class Gog extends Animal{
@Override
public void eat(){
System.out.println("吃骨头");
}
public void seedoor(){
System.out.println("看门");
}
}
案例演示孔子装爹
public class MyTest {
public static void main(String[] args) {
孔子爹 k爹 = new 孔子(); //多态:向上转型
System.out.println(k爹.age)//变量在这里访问父类的成员变量
k爹.teache();
孔子 k = (孔子) k爹; //向下转型
System.out.println(k.age);//变量在这里访问子类的成员变量
k.playGame(); //调用自己特有的方法
}
}
class 孔子爹 {
int age = 60;
public void teache() {
System.out.println("讲授JavaSE");
}
}
class 孔子 extends 孔子爹 {
int age = 30;
public void teache() {
System.out.println("讲授论语");
}
public void playGame() {
System.out.println("玩吃鸡游戏");
}
}
多态的内存图
多态分析题代码演示
1
public class DuoTaiTest3 {
public static void main(String[] args){
Fu f = new Zi();
// f.method();这里会出现报错,多态访问子类方法之前会先看父类有这个方法没,如果有就访问子类没有报错
f.show();
}
}
class Fu {
public void show() {
System.out.println("fu show");
}
}
class Zi extends Fu {
public void show() {
System.out.println("zi show");
}
public void method() {
System.out.println("zi method");
}
}
2
class A {
public void show() {
show2();
}
public void show2() {
System.out.println("我");
}
}
class B extends A {
public void show2() {
System.out.println("爱");
}
}
class C extends B {
public void show() {
super.show();
}
public void show2() {
System.out.println("你");
}
}
public class DuoTaiTest4 {
public static void main(String[] args) {
A a = new B();
a.show();
B b = new C();
b.show();
}
}
**输出结果为“爱你”**
抽象类
抽象类:在Java中,一个没有方法体的方法应该定义为抽象方法,而类中如果有抽象方法,该类必须定义为抽象类。
特点:抽象类和抽象方法必须用abstract关键字修饰
格式:abstract class 类名 {},
方法格式:public abstract void eat();
ps:(抽象类不一定有抽象方法,但是有抽象方法一定是抽象类,抽象类可以有构造方法用于访问父类数据时初始化。抽象类不能直接实例化,但是可以按照多态的形式与具体子类进行实例化,这也是多态的一种,抽象类多态,抽象类的子类要莫是抽象类,要莫重写方法)
代码演示
public class MyTest {
public static void main(String[] args) {
Animal an=new Cat();
an.eat();//子类改写过父类的方法
((Cat) an).play();//调用子类独有方法
an.ball();//调用父类方法
Animal an1=new Dog();
((Cat) an).play();//调用子类独有方法
an1.eat();//子类重写父类的方法
an1.ball();
}
}
abstract class Animal{
public abstract void eat();
public void ball(){
System.out.println("玩皮球");
}
}
class Cat extends Animal{//要么在这个类前面加上abstract让这个类变为一个抽象类,要么不加这个类必须改写父类的所有抽象方法使
// 抽象方法实例化
@Override
public void eat() {
System.out.println("吃鱼");
}
public void play(){
System.out.println("跑步");
}
}
class Dog extends Animal{
@Override
public void eat() {
System.out.println("吃骨头");
}
}
抽象类成员特点
- 成员变量:既可以是变量,也可以是常量。
- 构造方法:有,用于子类访问父类数据的初始化。
- 成员方法:既可以是抽象的,也可以是非抽象的。
抽象方法和非抽象方法的比较
- 抽象方法 强制要求子类做的事情。
- 非抽象方法 子类继承的事情,提高代码复用性
ps:(一个类如果没有抽象方法,可以定义为抽象类,但是这样没有意义,不能创建对象,)
abstract与private,final ,static , 不能共存没有意义
抽象类员工练习
public class MyTest {
public static void main(String[] args) {
Person p = new Jingli();
p.name = "王经理";
p.id = 1;
p.dongzi = 8900;
System.out.println(p.name);
System.out.println(p.id);
System.out.println(p.dongzi);
Jingli jingli = (Jingli) p;//向下转型调用经理的独有变量
System.out.println(jingli.jiangjin);//第一种方式
System.out.println(((Jingli) p).jiangjin);//第二种方式
p.work();
p = new Gongren();
p.name = "小王";
p.id = 2;
p.dongzi = 4500;
System.out.println(p.name);
System.out.println(p.id);
System.out.println(p.dongzi);
p.work();
}
}
abstract class Person {
public String name;
public int id;
public double dongzi;
public abstract void work();
}
class Jingli extends Person {
double jiangjin = 5000;
@Override
public void work() {
System.out.println("管理工作");
}
}
class Gongren extends Person {
@Override
public void work() {
System.out.println("一线工作");
}
}
//*结果
王经理
1
8900.0
5000.0
5000.0
管理工作
小王
2
4500.0
一线工作*//
接口
接口:所以,为了体现事物功能的扩展性,Java中就提供了接口来定义这些额外功能,并不给出具体实现,
特点:
- 接口用关键字interface表示 格式: interface 接口名 {}
- 类实现接口用implements表示 格式: class 类名 implements 接口名 {}
- 接口不能实例化
ps:(接口的子类可以是抽象类但是 意义不大,可以是具体类要重写接口所有的方法)
接口的成员特点
- 成员变量;只能是常量,并且是静态的。默认修饰符:public static final,手动给出
- 构造方法:接口没有构造方法。
- 成员方法:只能是抽象方法。默认修饰符:public abstract,手动给出,
**代码演示**
public interface MyInterface { //接口中语法特点
public static final int NUM=100; //公共的静态常量,
int B=10;//公共的静态常量 //前面有默认的修饰符 public static final
//接口中没有非抽象方法,全是抽象方法
public abstract void aa();
void bb(); //前面有默认的修饰符 public abstract
//public void hehe(){}; 报错,接口不能有非抽象方法
//接口中没有构造方法
}
public class MyTest {
public static void main(String[] args) {
int num = MyInterface.NUM;
System.out.println(num);
}
}
结果
100
代码演示
public class MyTest {
public static void main(String[] args) {
Animal a = new Cat();
a.eat();
a.play();
// a=new Dog();
Dog dog = new Dog();
a=dog;
a.play();
a.eat();
Fire fire=dog;
fire.wanhuo();
}
}
abstract class Animal{
public abstract void eat();
public abstract void play();
}
class Cat extends Animal{
@Override
public void eat() {
System.out.println("吃鱼");
}
@Override
public void play() {
System.out.println("玩老鼠");
}
}
class Dog extends Animal implements Fire{
@Override
public void wanhuo() {
System.out.println("玩火");
}
@Override
public void eat() {
System.out.println("吃骨头");
}
@Override
public void play() {
System.out.println("玩鸡");
}
}
interface Fire{
public abstract void wanhuo();
}
吃鱼
玩老鼠
玩鸡
吃骨头
玩火
类与类,类与接口,接口与接口的关系
- 类与类:继承关系,只能单继承,可以多层继承。
- 类与接口:实现关系,可以单实现,也可以多实现。并且还可以在继承一个类的同时实现多个接口。
- 接口与接口:继承关系,可以单继承,也可以多继承。
代码演示
public class MyTest {
public static void main(String[] args) {
//类跟类的关系
//类跟类的关系,是继承关系 extends,当自能是单继承
//类跟接口的关系
//类跟接口的关系,是实现关系,implments 实现可以多实现,一个类可以实现多个接口
//我们一个类可以在继承一个类的同时,并且也可以去实现一个或多个接口
//接口跟接口的关系
//接口跟接口有继承关系,而且支持多继承
}
}
abstract class Fu{
public abstract void fu();
}
interface A{
void a();
void aa();
}
interface B{
void b();
void bb();
}
interface C{
void c();
}
class MyClass extends Fu implements A,B,C{
@Override
public void a() {
}
@Override
public void aa() {
//空实现
}
@Override
public void b() {
}
@Override
public void bb() {
}
@Override
public void c() {
}
@Override
public void fu() {
}
}
interface AA{
void a();
void aa();
}
interface BB{
void b();
void bb();
}
interface CC extends AA,BB{
void cc();
}
class DD implements CC{
@Override
public void a() {
}
@Override
public void aa() {
}
@Override
public void b() {
}
@Override
public void bb() {
}
@Override
public void cc() {
}
}
抽象类和接口的区别
抽象类:
成员变量:可以变量,也可以常量
构造方法:有
成员方法:可以抽象,也可以非抽象
接口
成员变量:只可以常量
成员方法:只可以抽象
关系类别
类与类
继承,单继承
类与接口
实现,单实现,多实现
接口与接口
继承,单继承,多继承
设计理念
抽象类 被继承体现的是:”is a”的关系。 抽象类中定义的是该继承体系的共性功能。
接口 被实现体现的是:”like a”的关系。 接口中定义的是该继承体系的扩展功能。
ps:(JDK1.8之后在接口中提供了用default修饰的方法,可以给出功能的具体实现,子类可以继承下去用)