2020-07-27

面向对象

多态

多态的概述及其代码体现

多态概述

  • 某一个事物,在不同时刻表现出来的不同状态

  • 举例:

    Cat c=new Cat();

    Animal a=new Cat();

    猫可以是猫的类型。猫 m=new 猫();

    同时猫也是动物的一种,也可以把猫称为动物。动物 d=new 猫();

多态前提

  • 要有继承关系

  • 要有方法重写。其实也可以没有,但是如果没有这个就没有意义

  • 要有父类引用指向子类对象

    父 f=new 子();

多态中的成员访问特点

多态中的成员特点

  • 成员变量

    编译看左边,运行看左边

  • 构造方法

    创建子类对象的时候,会访问父类的构造方法,对父类的数据进行初始化

  • 成员方法

    编译看左边,运行看右边

  • 静态方法

    编译看左边,运行看左边

    (静态和类相关,算不上重写,所以访问还是左边)

public class MyTest {
    public static void main(String[] args) {
        //多态的形式,来看一下成员变量的特点
        //多态的形式来访问成员变量,编译看左边,运行也看左边。多态的形式访问成员变量,访问的都是父类的变量。
        Fu fu = new Zi();
        int n=fu.num;
        System.out.println(n);  //10
        //多态的形式,来访问成员方法的特点
        //编译看左边,运行看右边,编译期,看父类中有没有这个方法,如果有语法就报错,实际调用时,会以子类重写过后的为准。
        //当然,子类确实没有重写,那就以父类方法为准。
        fu.show();
        fu.jing();
        Fu.jing();
        Zi.jing();
        Zi zi = new Zi();

    }
}

class Fu{
    public Fu() {
        System.out.println("父类 构造调用了");
    }

    int num=100;
    public void show(){
        System.out.println("fu show");
    }
    public static void jing(){
        System.out.println("fu jing");
    }
}
class Zi extends Fu{
    int num=10;

    public Zi() {
        System.out.println("子类构造执行了");
    }

    @Override
    public void show() {
        System.out.println("zi show");
    }


    public static void jing() {
        System.out.println("zi jing");
    }
}
多态的好处

多态的好处

  • 提高了代码的维护性(继承保证)
  • 提高了代码的拓展性(由多态保证)
//我们现在设计的这个类,不好,扩展性不好,每增加一种动物,你就要增加一个重载的方法。
public class TestUtils {
    private TestUtils() {
    }

    //方法形参的设计,用成父类型,那么就可以接收他所有的子类型。能够提高代码的扩展性。
    public static void testEat(Animal an) {
        //父类引用指向子类对象,
        //多态形式调用成员方法,编译看左边,运行看右边
       // Animal an=cat
        //Animal an=dog
        //Animal an=tiger
        //Animal an=rabbit
        an.eat();
    }

   /* public static void testEat(Cat cat) {
        cat.eat();
    }

    public static void testEat(Dog dog) {
        dog.eat();
    }

    public static void testEat(Tiger tiger) {
        tiger.eat();
    }

    public static void testEat(Rabbit rabbit) {
        rabbit.eat();
    }*/
}

多态的弊端以及多态中向上转型和向下转型

多态的弊端

  • 不能使用子类特有功能
public class MyTest {
    public static void main(String[] args) {
        //多态的弊端:不能调用子类特有的功能
        Fu fu = new Zi();  //向上转型:多态就是向上转型。

        fu.show();
        //多态,不能直接调用,子类特有的功能。
        //fu.hehe(); 报错。

    /*    Zi zi = new Zi();
        zi.show();
        zi.hehe();
*/
       //我们可以采用向下转型,那调用子类特有的功能
        System.out.println(fu.num); //200
        Zi zi= (Zi) fu; //把父类引用,向下转型为子类型。
        zi.hehe();
        System.out.println(zi.num);  //10
    }
}
public class MyTest {
    public static void main(String[] args) {
        //09.05_ 案例演示 孔子装爹
        /*
        *  孔子爹,是一名Java讲师,非常有名,张三慕名前来,把孔子爹请到家里去讲课,此时就剩孔子一个人在家玩游戏。
        * 这时候,李四也来孔子的家里,请孔子爹去他家里讲课,那这时孔子爹不在家,这个孔子不想失去这笔生意,他就乔装打扮一下,打扮成他爹的模样,去李四家里给李四讲课。实际他讲的是论语。讲完之后,孔子回到家,觉得假扮他爹太累了,所以卸下装扮,做回他自己,愉快的玩游戏去了。
        *
        * */
        孔子爹 k爹= new 孔子();
        System.out.println(k爹.age);  //60;
        k爹.teach();
        //卸下装扮,做回我自己,向下转型。
        孔子 kz= (孔子) k爹;
        System.out.println(kz.age); //30
        kz.playGame();
    }
}

class 孔子爹{
    int age=60;
    public void teach(){
        System.out.println("讲授Java");
    }
}
class 孔子 extends 孔子爹{
    int age=30;

    @Override
    public void teach() {
        System.out.println("讲授论语");
    }
    public void playGame(){
        System.out.println("玩游戏");
    }
}
多态的内存图解

在这里插入图片描述

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");
		}
	}

	class DuoTaiTest3 {
		public static void main(String[] args){
			Fu f = new Zi();

			f.method(); //报错 ,不能直接调用子类特有的方法
			f.show();
		}
	}
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中,一个没有方法体的方法应该定义为抽象方法,而类中如果有抽象方法,该类必须定义为抽象类

抽象类特点

  • 抽象类和抽象方法方法必须用abstr关键字修饰

    抽象类格式: abstract class 类名 { }

    抽象方法格式: public abstract void eat();

  • 抽象类不一定有抽象方法,有抽象方法的类一定是抽象类

  • 抽象类中可以有构造方法,抽象类不能进行实例化,那么要构造方法有什么用呢?

    用于子类访问父类数据时的初始化

  • 抽象类不能直接实例化,那么抽象类该如何实例化呢?

    按照多态的方式,由具体的子类实例化,其实这也是多态的一种,抽象类多态

  • 抽象类的子类

    要么是抽象类

    要么重写抽象类中的所有抽象方法

public class MyTest {
    public static void main(String[] args) {
        //Animal animal = new Animal();
        Cat cat = new Cat();
        Dog dog = new Dog();
    }
}
//abstract 抽象的,可以修饰类,修饰方法。
abstract class Animal {
    //父类,他也不知道,子类对这个共性功能的具体实现,所以也没有必要给出共性功能的具体实现
    //抽象类,抽取所有子类的共性功能,但是不给出,共性功能的具体实现,而是交由子类根据自身的特性做以具体的实现。
    public abstract void eat();
    public abstract void sleep();
}

class Cat extends Animal {
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }

    @Override
    public void sleep() {
        System.out.println("猫白天睡觉");
    }
}

class Dog extends Animal {
    @Override
    public void eat() {
        System.out.println("狗吃骨头");
    }

    @Override
    public void sleep() {
        System.out.println("狗晚上睡觉");
    }
}
public class MyTest {
    public static void main(String[] args) {
        //抽象类的语法特点:
        //1.抽象类中,可以没有抽象方法,也可以有抽象方法。
        //2.一个类中,一旦有了抽象方法,此类就必须为抽象类。
        //3.抽象类,不能直接实例化,但是我们可以采用多态的形式,来间接实例化。
        //4.抽象类中所有抽象方法,强制子类必须重写
        //5.抽象类的子类有中选择,选择1.重写抽象类中的所有抽象方法,选择2:你自己也是个抽象类
        //6.可以没有抽象方法,也可以有抽象方法。这样设计的考虑,非抽象方法,可以让子类直接继承使用,对于抽象方法,是要求子类必须重写的。

    }
}
 abstract class A{
    public void show(){

    }
    public abstract void b();

     public abstract void c();
}

class B extends A {
    @Override
    public void b() {

    }

    @Override
    public void c() {

    }
}

abstract class C extends A {
        public abstract void cc();

}

class D extends C{

    @Override
    public void b() {

    }

    @Override
    public void c() {

    }

    @Override
    public void cc() {

    }
}
public class MyTest2 {
    public static void main(String[] args) {
        //抽象类,不能直接实例化,我们可以通过多态的形式,间接实例化父类
        Fu fu= new Zi();

    }
}

abstract class Fu{
    int num=20;
    final int A=200;
    //抽象类有构造方法,作用:用于子类访问父类数据时的初始化
    public Fu(){
        System.out.println("父类的构造执行了");
    }
}

class Zi extends Fu{
    public Zi() {
        System.out.println("子类的构造执行了");
    }
}
抽象类的成员特点

抽象类的成员特点

  • 成员变量:既可以是变量,也可以是常量(不被abstract修饰)

  • 构造方法:有

    用于子类访问父类数据的初始化

  • 成员方法:既可以是抽象的,也可以是非抽象的

抽象类的成员方法特性

  • 抽象方法 强制要求子类做的事情
  • 非抽象方法 子类继承的事情,提高代码的复用性
public class MyTest {
    public static void main(String[] args) {
       /* A:
        案例演示
        假如我们在开发一个系统时需要对员工(Employee) 类进行设计,员工包含3个属性:姓名、工号以及工资(salary)。
        经理(Manager) 也是员工,除了含有员工的属性外,另为还有一个奖金(bonus) 属性。
        然后定义工作的方法.
                请使用继承的思想设计出员工类和经理类。*/

        Person p = new Manager();
        p.name = "沈公子";
        p.id = 10;
        p.sal = 2000;
        System.out.println(p.name);
        System.out.println(p.id);
        System.out.println(p.sal);
        p.work();
        Manager m = (Manager) p;
        m.bonus = 6000;
        m.businessTrip();
        System.out.println(m.bonus);
        System.out.println("==================");
        p = new Employee();
        //类型转换异常。
        //java.lang.ClassCastException:org.westos.demo6.Manager cannot be cast to org.westos.demo6.Employee
        Employee e = (Employee) p;
        p.name = "王五";
        p.id = 22;
        p.sal = 1000;
        System.out.println(p.name);
        System.out.println(p.id);
        System.out.println(p.sal);
        p.work();

         //一个类如果没有抽象方法,可不可以定义为抽象类 ? 如果可以,有什么意义 ?
        //可以,这个类不想让外界创建对象。
         //abstract不能和哪些关键字共存 ?
          //private 矛盾 abstract 强制子类必须重写   private 私有的不能继承,重写不了
          // final 矛盾 final方法子类不能重写  abstract 又强制重写
          // static 方法不参与重写   abstract 他又要重写

    }
}
abstract class A{
    public abstract void hehe();
}

public abstract class Person {
    //姓名、工号以及工资(salary)。
    //工作的方法
    public String name;
    public int id;
    public double sal;

    public abstract void work();
}

public class Employee extends Person{
    @Override
    public void work() {
        System.out.println("员工在一线进行生产工作");
    }
}

public class Manager extends Person{
    double bonus;
    @Override
    public void work() {
        System.out.println("经理工作的内容是管理工作");
    }

    public void businessTrip(){
        System.out.println("经理需要出差");
    }
}

接口

接口的概述及其特点

接口概述

  • 为了体现事物功能的拓展性,java中就提供了接口来定义这些额外功能,并不给出具体事件,只需要在要实现这些功能的对象这里额外实现功能即可

接口特点

  • 接口用关键字interface表示 格式: interface 接口名 { }

  • 类实现接口用implements表示 格式: class 类名 implements 接口名 { }

  • 接口不能实例化

    接口按照多态的方式来实例化

  • 接口的子类

    可以是抽象类,但是意义不大

    可以是具体类,要重写接口中所有的抽象方法(推荐方案)

public class MyTest {
    public static void main(String[] args) {
        //接口:是为了定义一些额外扩展的功能,哪些事物,想要具备这些功能,可以对该接口进行实现。
        //接口不能实例化。
      /*  Animal an = new TomCat();
        an.sleep();
        an.eat();
        //父接口指向子类对象,这也是多态。
       MyInterface myInterface= new TomCat();

       myInterface.jump();*/
        TomCat tomCat = new TomCat();
        Animal an = tomCat;
        an.sleep();
        an.eat();
        MyInterface myInterface = tomCat;
        myInterface.jump();
        System.out.println("=============================");
        Dog dog = new Dog();
        myInterface= dog;
        myInterface.jump();
        an=dog;
        an.eat();
        an.sleep();

    }
}

// interface 定义一个接口
public interface MyInterface {
    //在接口中,提供扩展的功能
    public abstract void jump();
}

public abstract class Animal {
    public abstract void eat();
    public abstract void sleep();
}

public class Cat extends Animal {
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }

    @Override
    public void sleep() {
        System.out.println("猫白天睡觉");
    }

    public void catchMouse() {
        System.out.println("抓老鼠");
    }
}

public class TomCat extends Animal implements MyInterface {
    @Override
    public void eat() {
        System.out.println("汤姆猫爱吃小鱼干");
    }

    @Override
    public void sleep() {
        System.out.println("汤姆猫天天睡觉");
    }

    @Override
    public void jump() {
        System.out.println("汤姆猫,经过不断的练习学会了跳高");
    }
}

public class Dog extends  Animal implements MyInterface{
    @Override
    public void jump() {
        System.out.println("狗经过不断学习,学会为了跳高");
    }

    @Override
    public void eat() {
        System.out.println("狗吃骨头");
    }

    @Override
    public void sleep() {
        System.out.println("狗累了就睡觉");
    }
}
接口的成员特点

接口的成员特点

  • 成员变量:只能是常量,并且是静态的

    默认修饰符:public static final

    建议:自己手动给出

  • 构造方法:接口没有构造方法

  • 成员方法:只能是抽象方法

    默认修饰符:public abstract

    建议:自己手动给出

public class MyTest {
    public static void main(String[] args) {
        //接口的子类有两种选择:1.重写接口中的所有抽象方法,2.自己本身就是一个抽象类 但是意义不大。

        //接口中的成员特点:
        //1.接口中的成员变量,全部是公共的静态常量 前面存在默认修饰符  public static final
        System.out.println(A.NUM); //接口名直接调用
        //2.JDK1.7 之前接口中的方法,全部是抽象方法,不存在非抽象方法。方法的前面存在 默认修饰符 public abstract
        //3.接口中没有构造方法这一说。
        //4.接口不能直接new对象。
    }
}

interface A{
    public static final int NUM=100;
    int N=20;
    public abstract void a();
    public abstract void aa();

     int sum(int a,int b);
}
 class B implements A{

     @Override
     public void a() {

     }

     @Override
     public void aa() {

     }

     @Override
     public int sum(int a, int b) {
         return 0;
     }
 }
类与类、类与接口、接口与接口的关系

类与类、类与接口、接口与接口的关系

  • 类与类

    继承关系,只能单继承,可以多层继承

  • 类与接口

    实现关系,可以单实现,也可以多实现

    并且还可以在继承一个类的同时实现多个接口

  • 接口与接口

    继承关系,可以单继承,也可以多继承

public class MyTest2 {
    public static void main(String[] args) {
        //类和类之间的关系: extends  继承关系 并且是单继承。
        //类和接口之间的关系:implements 实现关系,并且可以多实现。
        //接口和接口之间的关系:extends  继承关系 并且还是多继承。一个接口可以继承多个接口。
    }
}

interface AA{
    void aa();
}

interface BB{
    void bb();
}

interface CC{
    void cc();
}
interface DD  extends AA,BB,CC{
    void dd();

}

class MyDD implements DD{

    @Override
    public void aa() {

    }

    @Override
    public void bb() {

    }

    @Override
    public void cc() {

    }

    @Override
    public void dd() {

    }
}
//一个类 可以实现多个接口。这个类,要把他所有实现的接口中的所有抽象方法都要重写。
class MyClss implements AA,BB,CC{

    @Override
    public void aa() {

    }

    @Override
    public void bb() {

    }

    @Override
    public void cc() {

    }
}
抽象类和接口的区别

成员区别

  • 抽象类:

    成员变量:可以是变量,也可以是常量

    构造方法:有

    成员方法:可以抽象,也可以非抽象

  • 接口:

    成员变量:只可以常量

    成员方法:只可以抽象

关系区别

  • 类与类

    继承、单继承

  • 类与接口

    实现、单实现、多实现

  • 接口与接口

    继承、单继承、多继承

设计理念区别

  • 抽象类 被继承体现的是:“is a”的关系。 抽象类中定义的是该继承体系的共性功能
  • 接口 被实现体现的是:“lika a”的关系。 接口中定义的是该继承体系的拓展功能
public class MyTest {
    public static void main(String[] args) {
        //JDK1.8之后针对接口,做了一些新的定义。
        //JDK1.8之后,他允许给出方法的具体实现,但是这个方法得用default来修饰。
        //JDK1.8之后,接口中可以定义静态方法
        //Java中的接口,更多的是来定义一些规则和规范的,以实现这个扩展性。
        Zi zi = new Zi();
        zi.aa();
        zi.bb();
        AA.test();

    }
}

interface AA{
   // void ccc();
   public default void aa(){
       System.out.println("aaa");
   }
   public static void test(){
       System.out.println("abc");
   }
}

interface BB {
   default void bb(){
       System.out.println("bbb");
   }
}

class Fu1{
    public void show(){
        System.out.println("fu1 show");
    }
}

class Fu2 {
    public void show2() {
        System.out.println("fu2 show");
    }
}

class Zi implements AA,BB{

//抽象类和接口的区别
        //抽象类中,可以定义抽象方法,也可以定义非抽象方法。
        //接口:接口里面定义的是抽象方法,JDK1.8可以定义 default修饰的方法和静态方法。
        //抽象类有构造方法的,接口没有构造方法这一说。
        //抽象类可以定义成员变量也可以定义常量,接口中全是公共的静态常量。
        //设计思想:抽象类,他是抽象所有子类的共性功能,并不给出共性功能的具体实现,而是交由子类根据自身的差异性,去做具体实现。
        //接口:体现一种扩展的思想,通常用来定义一些规范和规则,哪些事物想要具备这些扩展功能,可以实现具体的接口。接口他只需要维护一套规范或者说规则,那么具体对规范的实现,是由子类来具体实现的。

}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值