09_面向对象(final关键字、多态的概述和讲解、抽象类的概述和讲解、接口的概述和讲解)

1:final关键字(掌握)
    (1)是最终的意思,可以修饰类,方法,变量。
    (2)特点:
        A:它修饰的类,不能被继承。
        B:它修饰的方法,不能被重写。
        C:它修饰的变量,是一个常量。
    (3)面试相关:
        A:局部变量
            a:基本类型 值不能发生改变
            b:引用类型 地址值不能发生改变,但是对象的内容是可以改变的
        B:初始化时机
            a:只能初始化一次。
            b:常见的给值
                定义的时候。(推荐)
                构造方法中。

FinalDemo.java

/*
    final可以修饰类,方法,变量
    
    特点:
        final可以修饰类,该类不能被继承。
        final可以修饰方法,该方法不能被重写。(覆盖,复写)
        final可以修饰变量,该变量不能被重新赋值。因为这个变量其实常量。
        
    常量:
        A:字面值常量
            "hello",10,true
        B:自定义常量
            final int x = 10;
*/

//final class Fu //无法从最终Fu进行继承

class Fu {
    public int num = 10;
    public final int num2 = 20;

    /*
    public final void show() {
    
    }
    */
}

class Zi extends Fu {
    // Zi中的show()无法覆盖Fu中的show()
    public void show() {
        num = 100;
        System.out.println(num);
        
        //无法为最终变量num2分配值
        //num2 = 200;
        System.out.println(num2);
    }
}

class FinalDemo {
    public static void main(String[] args) {
        Zi z = new Zi();
        z.show();
    }
}

FinalTest.java

/*
    面试题:final修饰局部变量的问题
        基本类型:基本类型的值不能发生改变。
        引用类型:引用类型的地址值不能发生改变,但是,该对象的堆内存的值是可以改变的。
*/
class Student {
    int age = 10;
}

class FinalTest {
    public static void main(String[] args) {
        //局部变量是基本数据类型
        int x = 10;
        x = 100;
        System.out.println(x);
        final int y = 10;
        //无法为最终变量y分配值
        //y = 100;
        System.out.println(y);
        System.out.println("--------------");
        
        //局部变量是引用数据类型
        Student s = new Student();
        System.out.println(s.age);
        s.age = 100;
        System.out.println(s.age);
        System.out.println("--------------");
        
        final Student ss = new Student();
        System.out.println(ss.age);
        ss.age = 100;
        System.out.println(ss.age);
        
        //重新分配内存空间
        //无法为最终变量ss分配值
        ss = new Student();
    }
}

FinalTest2.java

 

/*
    final修饰变量的初始化时机
        A:被final修饰的变量只能赋值一次。
        B:在构造方法完毕前。(非静态的常量)
*/
class Demo {
    //int num = 10;
    //final int num2 = 20;
    
    int num;
    final int num2;
    
    {
        //num2 = 10;
    }
    
    public Demo() {
        num = 100;
        //无法为最终变量num2分配值
        num2 = 200;
    }
}

class FinalTest2 {
    public static void main(String[] args) {
        Demo d = new Demo();
        System.out.println(d.num);
        System.out.println(d.num2);
    }
}

ZiDemo.java

/*
    继承的代码体现
    
    由于继承中方法有一个现象:方法重写。
    所以,父类的功能,就会被子类给覆盖调。
    有些时候,我们不想让子类去覆盖掉父类的功能,只能让他使用。
    这个时候,针对这种情况,Java就提供了一个关键字:final
    
    final:最终的意思。常见的是它可以修饰类,方法,变量。
*/
class Fu {
    public final void show() {
        System.out.println("这里是绝密资源,任何人都不能修改");
    }
}

class Zi extends Fu {
    // Zi中的show()无法覆盖Fu中的show()
    public void show() {
        System.out.println("这是一堆垃圾");
    }
}

class ZiDemo {
    public static void main(String[] args) {
        Zi z = new Zi();
        z.show();
    }
}

   
2:多态(掌握)
    (1)同一个对象在不同时刻体现出来的不同状态。
    (2)多态的前提:
        A:有继承或者实现关系。
        B:有方法重写。
        C:有父类或者父接口引用指向子类对象。
        
        多态的分类:
            a:具体类多态
                class Fu {}
                class Zi extends Fu {}
                
                Fu f = new Zi();
            b:抽象类多态
                abstract class Fu {}
                class Zi extends Fu {}
                
                Fu f = new Zi();
            c:接口多态
                interface Fu {}
                class Zi implements Fu {}
                
                Fu f = new Zi();
    (3)多态中的成员访问特点
        A:成员变量
            编译看左边,运行看左边
        B:构造方法
            子类的构造都会默认访问父类构造
        C:成员方法
            编译看左边,运行看右边
        D:静态方法
            编译看左边,运行看左边
            
        为什么?
            因为成员方法有重写。
    (4)多态的好处:
        A:提高代码的维护性(继承体现)
        B:提高代码的扩展性(多态体现)
    (5)多态的弊端:
        父不能使用子的特有功能。
        
        现象:
            子可以当作父使用,父不能当作子使用。
    (6)多态中的转型
        A:向上转型
            从子到父
        B:向下转型
            从父到子
    (7)孔子装爹的案例帮助大家理解多态
    (8)多态的练习
        A:猫狗案例
        B:老师和学生案例

DuoTaiDemo.java

/*
    多态:同一个对象(事物),在不同时刻体现出来的不同状态。
    举例:
        猫是猫,猫是动物。
        水(液体,固体,气态)。
        
    多态的前提:
        A:要有继承关系。
        B:要有方法重写。
            其实没有也是可以的,但是如果没有这个就没有意义。
                动物 d = new 猫();
                d.show();
                动物 d = new 狗();
                d.show();
        C:要有父类引用指向子类对象。
            父 f =  new 子();
            
    用代码体现一下多态。
    
    多态中的成员访问特点:
        A:成员变量
            编译看左边,运行看左边。
        B:构造方法
            创建子类对象的时候,访问父类的构造方法,对父类的数据进行初始化。
        C:成员方法
            编译看左边,运行看右边。
        D:静态方法
            编译看左边,运行看左边。
            (静态和类相关,算不上重写,所以,访问还是左边的)
            
        由于成员方法存在方法重写,所以它运行看右边。
*/
class Fu {
    public int num = 100;

    public void show() {
        System.out.println("show Fu");
    }
    
    public static void function() {
        System.out.println("function Fu");
    }
}

class Zi extends Fu {
    public int num = 1000;
    public int num2 = 200;

    public void show() {
        System.out.println("show Zi");
    }
    
    public void method() {
        System.out.println("method zi");
    }
    
    public static void function() {
        System.out.println("function Zi");
    }
}

class DuoTaiDemo {
    public static void main(String[] args) {
        //要有父类引用指向子类对象。
        //父 f =  new 子();
        Fu f = new Zi();
        System.out.println(f.num);
        //找不到符号
        //System.out.println(f.num2);
        
        f.show();
        //找不到符号
        //f.method();
        f.function();
    }
}

DuoTaiDemo2.java

/*
    多态的好处:
        A:提高了代码的维护性(继承保证)
        B:提高了代码的扩展性(由多态保证)
        
    猫狗案例代码
*/
class Animal {
    public void eat(){
        System.out.println("eat");
    }
    
    public void sleep(){
        System.out.println("sleep");
    }
}

class Dog extends Animal {
    public void eat(){
        System.out.println("狗吃肉");
    }
    
    public void sleep(){
        System.out.println("狗站着睡觉");
    }
}

class Cat extends Animal {
    public void eat() {
        System.out.println("猫吃鱼");
    }
    
    public void sleep() {
        System.out.println("猫趴着睡觉");
    }
}

class Pig extends Animal {
    public void eat() {
        System.out.println("猪吃白菜");
    }
    
    public void sleep() {
        System.out.println("猪侧着睡");
    }
}

//针对动物操作的工具类
class AnimalTool {
    private AnimalTool(){}

    /*
    //调用猫的功能
    public static void useCat(Cat c) {
        c.eat();
        c.sleep();
    }
    
    //调用狗的功能
    public static void useDog(Dog d) {
        d.eat();
        d.sleep();
    }
    
    //调用猪的功能
    public static void usePig(Pig p) {
        p.eat();
        p.sleep();
    }
    */
    public static void useAnimal(Animal a) {
        a.eat();
        a.sleep();
    }
    
}

class DuoTaiDemo2 {
    public static void main(String[] args) {
        //我喜欢猫,就养了一只
        Cat c = new Cat();
        c.eat();
        c.sleep();
        
        //我很喜欢猫,所以,又养了一只
        Cat c2 = new Cat();
        c2.eat();
        c2.sleep();
        
        //我特别喜欢猫,又养了一只
        Cat c3 = new Cat();
        c3.eat();
        c3.sleep();
        //...
        System.out.println("--------------");
        //问题来了,我养了很多只猫,每次创建对象是可以接受的
        //但是呢?调用方法,你不觉得很相似吗?仅仅是对象名不一样。
        //我们准备用方法改进
        //调用方式改进版本
        //useCat(c);
        //useCat(c2);
        //useCat(c3);
        
        //AnimalTool.useCat(c);
        //AnimalTool.useCat(c2);
        //AnimalTool.useCat(c3);
        
        AnimalTool.useAnimal(c);
        AnimalTool.useAnimal(c2);
        AnimalTool.useAnimal(c3);
        System.out.println("--------------");
        
        //我喜欢狗
        Dog d = new Dog();
        Dog d2 = new Dog();
        Dog d3 = new Dog();
        //AnimalTool.useDog(d);
        //AnimalTool.useDog(d2);
        //AnimalTool.useDog(d3);
        AnimalTool.useAnimal(d);
        AnimalTool.useAnimal(d2);
        AnimalTool.useAnimal(d3);
        System.out.println("--------------");
        
        //我喜欢宠物猪
        //定义一个猪类,它要继承自动物,提供两个方法,并且还得在工具类中添加该类方法调用
        Pig p = new Pig();
        Pig p2 = new Pig();
        Pig p3 = new Pig();
        //AnimalTool.usePig(p);
        //AnimalTool.usePig(p2);
        //AnimalTool.usePig(p3);
        AnimalTool.useAnimal(p);
        AnimalTool.useAnimal(p2);
        AnimalTool.useAnimal(p3);
        System.out.println("--------------");
        
        //我喜欢宠物狼,老虎,豹子...
        //定义对应的类,继承自动物,提供对应的方法重写,并在工具类添加方法调用
        //前面几个必须写,我是没有意见的
        //但是,工具类每次都改,麻烦不
        //我就想,你能不能不改了
        //太简单:把所有的动物都写上。问题是名字是什么呢?到底哪些需要被加入呢?
        //改用另一种解决方案。
        
    }
    
    /*
    //调用猫的功能
    public static void useCat(Cat c) {
        c.eat();
        c.sleep();
    }
    
    //调用狗的功能
    public static void useDog(Dog d) {
        d.eat();
        d.sleep();
    }
    */
}

DuoTaiDemo3.java

/*
    多态的弊端:
        不能使用子类的特有功能。
*/
class Fu {
    public void show() {
        System.out.println("show fu");
    }
}

class Zi extends Fu {
    public void show() {
        System.out.println("show zi");
    }
    
    public void method() {
        System.out.println("method zi");
    }

}

class DuoTaiDemo3 {
    public static void main(String[] args) {
        //测试
        Fu f = new Zi();
        f.show();
        f.method();
    }
}

 

DuoTaiDemo4.java

/*
    多态的弊端:
        不能使用子类的特有功能。
        
    我就想使用子类的特有功能?行不行?
        行。
        
    怎么用呢?
        A:创建子类对象调用方法即可。(可以,但是很多时候不合理。而且,太占内存了)
        B:把父类的引用强制转换为子类的引用。(向下转型)
        
    对象间的转型问题:
        向上转型:
            Fu f = new Zi();
        向下转型:
            Zi z = (Zi)f; //要求该f必须是能够转换为Zi的。
*/
class Fu {
    public void show() {
        System.out.println("show fu");
    }
}

class Zi extends Fu {
    public void show() {
        System.out.println("show zi");
    }
    
    public void method() {
        System.out.println("method zi");
    }

}

class DuoTaiDemo4 {
    public static void main(String[] args) {
        //测试
        Fu f = new Zi();
        f.show();
        //f.method();
        
        //创建子类对象
        //Zi z = new Zi();
        //z.show();
        //z.method();
        
        //你能够把子的对象赋值给父亲,那么我能不能把父的引用赋值给子的引用呢?
        //如果可以,但是如下
        Zi z = (Zi)f;
        z.show();
        z.method();
    }
}

DuoTaiDemo5.java

/*
    ClassCastException:类型转换异常
    一般在多态的向下转型中容易出现
*/
class Animal {
    public void eat(){}
}

class Dog extends Animal {
    public void eat() {}
    
    public void lookDoor() {
    
    }
}

class Cat extends Animal {
    public void eat() {
    
    }
    
    public void playGame() {
        
    }
}

class DuoTaiDemo5 {
    public static void main(String[] args) {
        //内存中的是狗
        Animal a = new Dog();
        Dog d = (Dog)a;
        
        //内存中是猫
        a = new Cat();
        Cat c = (Cat)a;
        
        //内存中是猫
        Dog dd = (Dog)a; //ClassCastException
    }
}

 DuoTaiTest.java

/*
    多态练习:猫狗案例
*/
class Animal {
    public void eat(){
        System.out.println("吃饭");
    }
}

class Dog extends Animal {
    public void eat() {
        System.out.println("狗吃肉");
    }
    
    public void lookDoor() {
        System.out.println("狗看门");
    }
}

class Cat extends Animal {
    public void eat() {
        System.out.println("猫吃鱼");
    }
    
    public void playGame() {
        System.out.println("猫捉迷藏");
    }
}

class DuoTaiTest {
    public static void main(String[] args) {
        //定义为狗
        Animal a = new Dog();
        a.eat();
        System.out.println("--------------");
        //还原成狗
        Dog d = (Dog)a;
        d.eat();
        d.lookDoor();
        System.out.println("--------------");
        //变成猫
        a = new Cat();
        a.eat();
        System.out.println("--------------");
        //还原成猫
        Cat c = (Cat)a;
        c.eat();
        c.playGame();
        System.out.println("--------------");
        
        //演示错误的内容
        //Dog dd = new Animal();
        //Dog ddd = new Cat();
        //ClassCastException
        //Dog dd = (Dog)a;
    }
}    

DuoTaiTest2.java

/*
    不同地方饮食文化不同的案例
*/
class Person {
    public void eat() {
        System.out.println("吃饭");
    }
}

class SouthPerson extends Person {
    public void eat() {
        System.out.println("炒菜,吃米饭");
    }
    
    public void jingShang() {
        System.out.println("经商");
    }
}

class NorthPerson extends Person {
    public void eat() {
        System.out.println("炖菜,吃馒头");
    }
    
    public void yanJiu() {
        System.out.println("研究");
    }
}

class DuoTaiTest2 {
    public static void main(String[] args) {
        //测试
        //南方人
        Person p = new SouthPerson();
        p.eat();
        System.out.println("-------------");
        SouthPerson sp = (SouthPerson)p;
        sp.eat();
        sp.jingShang();
        System.out.println("-------------");
        
        //北方人
        p = new NorthPerson();
        p.eat();
        System.out.println("-------------");
        NorthPerson np = (NorthPerson)p;
        np.eat();
        np.yanJiu();
    }
}

DuoTaiTest3.java

/*
    看程序写结果:先判断有没有问题,如果没有,写出结果
*/
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();
    }
}

DuoTaiTest4.java

/*
    看程序写结果:先判断有没有问题,如果没有,写出结果
    
    多态的成员访问特点:
        方法:编译看左边,运行看右边。
        
    继承的时候:
        子类中有和父类中一样的方法,叫重写。
        子类中没有父亲中出现过的方法,方法就被继承过来了。
*/
class A {
    public void show() {
        show2();
    }
    public void show2() {
        System.out.println("我");
    }
}
class B extends A {
    /*
    public void show() {
        show2();
    }
    */

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

 
3:抽象类(掌握)
    (1)把多个共性的东西提取到一个类中,这是继承的做法。
       但是呢,这多个共性的东西,在有些时候,方法声明一样,但是方法体。
       也就是说,方法声明一样,但是每个具体的对象在具体实现的时候内容不一样。
       所以,我们在定义这些共性的方法的时候,就不能给出具体的方法体。
       而一个没有具体的方法体的方法是抽象的方法。
       在一个类中如果有抽象方法,该类必须定义为抽象类。
    (2)抽象类的特点
        A:抽象类和抽象方法必须用关键字abstract修饰
        B:抽象类中不一定有抽象方法,但是有抽象方法的类一定是抽象类
        C:抽象类不能实例化
        D:抽象类的子类
            a:是一个抽象类。
            b:是一个具体类。这个类必须重写抽象类中的所有抽象方法。
    (3)抽象类的成员特点:
        A:成员变量
            有变量,有常量
        B:构造方法
            有构造方法
        C:成员方法
            有抽象,有非抽象
    (4)抽象类的练习
        A:猫狗案例练习
        B:老师案例练习
        C:学生案例练习
        D:员工案例练习
    (5)抽象类的几个小问题
        A:抽象类有构造方法,不能实例化,那么构造方法有什么用?
            用于子类访问父类数据的初始化
        B:一个类如果没有抽象方法,却定义为了抽象类,有什么用?
            为了不让创建对象
        C:abstract不能和哪些关键字共存
            a:final    冲突
            b:private 冲突
            c:static 无意义

AbstractDemo.java

/*
    抽象类的概述:
        动物不应该定义为具体的东西,而且动物中的吃,睡等也不应该是具体的。
        我们把一个不是具体的功能称为抽象的功能,而一个类中如果有抽象的功能,该类必须是抽象类。
        
    抽象类的特点:
        A:抽象类和抽象方法必须用abstract关键字修饰
        B:抽象类中不一定有抽象方法,但是有抽象方法的类必须定义为抽象类
        C:抽象类不能实例化
            因为它不是具体的。
            抽象类有构造方法,但是不能实例化?构造方法的作用是什么呢?
            用于子类访问父类数据的初始化
        D:抽象的子类
            a:如果不想重写抽象方法,该子类是一个抽象类。
            b:重写所有的抽象方法,这个时候子类是一个具体的类。
            
        抽象类的实例化其实是靠具体的子类实现的。是多态的方式。
            Animal a = new Cat();
*/

//abstract class Animal //抽象类的声明格式
abstract class Animal {
    //抽象方法
    //public abstract void eat(){} //空方法体,这个会报错。抽象方法不能有主体
    public abstract void eat();
    
    public Animal(){}
}

//子类是抽象类
abstract class Dog extends Animal {}

//子类是具体类,重写抽象方法
class Cat extends Animal {
    public void eat() {
        System.out.println("猫吃鱼");
    }
}

class AbstractDemo {
    public static void main(String[] args) {
        //创建对象
        //Animal是抽象的; 无法实例化
        //Animal a = new Animal();
        //通过多态的方式
        Animal a = new Cat();
        a.eat();
    }
}

AbstractDemo2.java

/*
    抽象类的成员特点:
        成员变量:既可以是变量,也可以是常量。
        构造方法:有。
                    用于子类访问父类数据的初始化。
        成员方法:既可以是抽象的,也可以是非抽象的。
        
    抽象类的成员方法特性:
        A:抽象方法 强制要求子类做的事情。
        B:非抽象方法 子类继承的事情,提高代码复用性。
*/
abstract class Animal {
    public int num = 10;
    public final int num2 = 20;

    public Animal() {}
    
    public Animal(String name,int age){}
    
    public abstract void show();
    
    public void method() {
        System.out.println("method");
    }
}

class Dog extends Animal {
    public void show() {
        System.out.println("show Dog");
    }
}

class AbstractDemo2 {
    public static void main(String[] args) {
        //创建对象
        Animal a = new Dog();
        a.num = 100;
        System.out.println(a.num);
        //a.num2 = 200;
        System.out.println(a.num2);
        System.out.println("--------------");
        a.show();
        a.method();
    }
}

AbstractDemo3.java

/*
一个类如果没有抽象方法,可不可以定义为抽象类?如果可以,有什么意义?
    A:可以。
    B:不让创建对象。

abstract不能和哪些关键字共存?
    private    冲突
    final    冲突    
    static    无意义
*/
abstract class Fu {
    //public abstract void show();
    //非法的修饰符组合: abstract和private
    //private abstract void show();
    
    //非法的修饰符组合
    //final abstract void show();    
    
    //非法的修饰符组合
    static abstract void show();
    
    public static void method() {
        System.out.println("method");
    }
}

class Zi extends Fu {
    public void show() {}
}

class AbstractDemo3 {
    public static void main(String[] args) {
        Fu.method();
    }
}

 AbstractTest.java

/*
    猫狗案例
        具体事物:猫,狗
        共性:姓名,年龄,吃饭

    分析:从具体到抽象
        猫:
            成员变量:姓名,年龄
            构造方法:无参,带参
            成员方法:吃饭(猫吃鱼)
            
        狗:
            成员变量:姓名,年龄
            构造方法:无参,带参
            成员方法:吃饭(狗吃肉)
            
        因为有共性的内容,所以就提取了一个父类。动物。
        但是又由于吃饭的内容不一样,所以吃饭的方法是抽象的,
        而方法是抽象的类,类就必须定义为抽象类。
        
        抽象动物类:
            成员变量:姓名,年龄
            构造方法:无参,带参
            成员方法:吃饭();
    
    实现:从抽象到具体
        动物类:
            成员变量:姓名,年龄
            构造方法:无参,带参
            成员方法:吃饭();
            
        狗类:
            继承自动物类
            重写吃饭();
            
        猫类:
            继承自动物类
            重写吃饭();
*/
//定义抽象的动物类
abstract class Animal {
    //姓名
    private String name;
    //年龄
    private int age;
    
    public Animal() {}
    
    public Animal(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 abstract void eat();
}

//定义具体的狗类
class Dog extends Animal {
    public Dog() {}
    
    public Dog(String name,int age) {
        super(name,age);
    }
    
    public void eat() {
        System.out.println("狗吃肉");
    }
}

//定义具体的猫类
class Cat extends Animal {
    public Cat() {}
    
    public Cat(String name,int age) {
        super(name,age);
    }
    
    public void eat() {
        System.out.println("猫吃鱼");
    }
}

//测试类
class AbstractTest {
    public static void main(String[] args) {
        //测试狗类
        //具体类用法
        //方式1:
        Dog d = new Dog();
        d.setName("旺财");
        d.setAge(3);
        System.out.println(d.getName()+"---"+d.getAge());
        d.eat();
        //方式2:
        Dog d2 = new Dog("旺财",3);
        System.out.println(d2.getName()+"---"+d2.getAge());
        d2.eat();
        System.out.println("---------------------------");
        
        Animal a = new Dog();
        a.setName("旺财");
        a.setAge(3);
        System.out.println(a.getName()+"---"+a.getAge());
        a.eat();
        
        Animal a2 = new Dog("旺财",3);
        System.out.println(a2.getName()+"---"+a2.getAge());
        a2.eat();
        
        //练习:测试猫类
    }
}

 AbstractTest2.java

/*
    老师案例
        具体事物:基础班老师,就业班老师
        共性:姓名,年龄,讲课。

    分析:    
        基础班老师
            姓名,年龄
            讲课。
        就业班老师
            姓名,年龄
            讲课。
    实现:
        老师类
            基础班老师
            就业班老师
*/
//定义抽象的老师类
abstract class Teacher {
    //姓名
    private String name;
    //年龄
    private int age;
    
    public Teacher() {}
    
    public Teacher(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 abstract void teach();
}

//基础班老师类
class BasicTeacher extends Teacher {
    public BasicTeacher(){}
    
    public BasicTeacher(String name,int age) {
        super(name,age);
    }
    
    public void teach() {
        System.out.println("基础班老师讲解JavaSE");
    }
}

//就业班老师类
class WorkTeacher extends Teacher {
    public WorkTeacher(){}
    
    public WorkTeacher(String name,int age) {
        super(name,age);
    }
    
    public void teach() {
        System.out.println("就业班老师讲解JavaEE");
    }
}

class AbstractTest2 {
    public static void main(String[] args) {
        //具体的类测试,自己玩
        
        //测试(多态)
        //基础班老师
        Teacher t = new BasicTeacher();
        t.setName("刘意");
        t.setAge(30);
        System.out.println(t.getName()+"---"+t.getAge());
        t.teach();
        System.out.println("--------------");
        
        t = new BasicTeacher("刘意",30);
        System.out.println(t.getName()+"---"+t.getAge());
        t.teach();
        System.out.println("--------------");
        
        //就业班老师
        t = new WorkTeacher();
        t.setName("林青霞");
        t.setAge(27);
        System.out.println(t.getName()+"---"+t.getAge());
        t.teach();
        System.out.println("--------------");
        
        t = new WorkTeacher("林青霞",27);
        System.out.println(t.getName()+"---"+t.getAge());
        t.teach();
    }
}

AbstractTest3.java

/*
    学生案例
        具体事务:基础班学员,就业班学员
        共性:姓名,年龄,班级,学习,吃饭

    分析:
        基础班学员
            成员变量:姓名,年龄,班级
            成员方法:学习,吃饭
        就业班学员
            成员变量:姓名,年龄,班级
            成员方法:学习,吃饭
            
        得到一个学员类。
            成员变量:姓名,年龄,班级
            成员方法:学习,吃饭
            
    实现:
        学员类
        基础班学员
        就业班学员
*/
//定义抽象学员类
abstract class Student {
    //姓名
    private String name;
    //年龄
    private int age;
    //班级
    private String grand;
    
    public Student() {}
    
    public Student(String name,int age,String grand) {
        this.name = name;
        this.age = age;
        this.grand = grand;
    }
    
    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 String getGrand() {
        return grand;
    }
    
    public void setGrand(String grand) {
        this.grand = grand;
    }
    
    //学习
    public abstract void study();
    
    //吃饭
    public void eat() {
        System.out.println("学习累了,就该吃饭");
    }
}

//具体基础班学员类
class BasicStudent extends Student {
    public BasicStudent() {}
    
    public BasicStudent(String name,int age,String grand) {
        super(name,age,grand);
    }
    
    public void study() {
        System.out.println("基础班学员学习的是JavaSE");
    }
}

//具体就业班学员类
class WorkStudent extends Student {
    public WorkStudent() {}
    
    public WorkStudent(String name,int age,String grand) {
        super(name,age,grand);
    }
    
    public void study() {
        System.out.println("就业班学员学习的是JavaEE");
    }
}

class AbstractTest3 {
    public static void main(String[] args) {
        //我仅仅测试基础班学员
        //按照多态的方式测试
        Student s = new BasicStudent();
        s.setName("林青霞");
        s.setAge(27);
        s.setGrand("1111");
        System.out.println(s.getName()+"---"+s.getAge()+"---"+s.getGrand());
        s.study();
        s.eat();
        System.out.println("--------------");
        
        s = new BasicStudent("武鑫",48,"1111");
        System.out.println(s.getName()+"---"+s.getAge()+"---"+s.getGrand());
        s.study();
        s.eat();
        
        //就业班测试留给自己玩
    }
}

 AbstractTest4.java

/*
    假如我们在开发一个系统时需要对员工类进行设计,员工包含3个属性:姓名、工号以及工资。
    经理也是员工,除了含有员工的属性外,另为还有一个奖金属性。
    请使用继承的思想设计出员工类和经理类。要求类中提供必要的方法进行属性访问。
    
    分析:
        普通员工类
            成员变量:姓名、工号以及工资。
            成员方法:工作
        经理类:
            成员变量:姓名、工号以及工资,奖金属性
            成员方法:工作
            
    实现:
        员工类:
        普通员工类:
        经理类:
*/
//定义员工类
abstract class Employee {
    //姓名、工号以及工资
    private String name;
    private String id;
    private int salary;
    
    public Employee() {}
    
    public Employee(String name,String id,int salary) {
        this.name = name;
        this.id = id;
        this.salary = salary;
    }
    
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    public String getId() {
        return id;
    }
    
    public void setId(String id) {
        this.id = id;
    }
    
    public int getSalary() {
        return salary;
    }
    
    public void setSalary(int salary) {
        this.salary = salary;
    }
    
    //工作
    public abstract void work();
}

//普通员工类
class Programmer extends Employee {
    public Programmer(){}
    
    public Programmer(String name,String id,int salary) {
        super(name,id,salary);
    }
    
    public void work() {
        System.out.println("按照需求写代码");
    }
}

//经理类
class Manager extends Employee {
    //奖金
    private int money; //bonus 奖金

    public Manager(){}
    
    public Manager(String name,String id,int salary,int money) {
        super(name,id,salary);
        this.money = money;
    }
    
    public void work() {
        System.out.println("跟客户谈需求");
    }
    
    public int getMoney() {
        return money;
    }
    
    public void setMoney(int money) {
        this.money = money;
    }
}

class AbstractTest4 {
    public static void main(String[] args) {
        //测试普通员工
        Employee emp = new Programmer();
        emp.setName("林青霞");
        emp.setId("czbk001");
        emp.setSalary(18000);
        System.out.println(emp.getName()+"---"+emp.getId()+"---"+emp.getSalary());
        emp.work();
        System.out.println("-------------");
        emp = new Programmer("林青霞","czbk001",18000);
        System.out.println(emp.getName()+"---"+emp.getId()+"---"+emp.getSalary());
        emp.work();
        System.out.println("-------------");
        
        /*
        emp = new Manager();
        emp.setName("刘意");
        emp.setId("czbk002");
        emp.setSalary(8000);
        emp.setMoney(2000);
        */
        //由于子类有特有的内容,所以我们用子类来测试
        Manager m = new Manager();
        m.setName("刘意");
        m.setId("czbk002");
        m.setSalary(8000);
        m.setMoney(2000);
        System.out.println(m.getName()+"---"+m.getId()+"---"+m.getSalary()+"---"+m.getMoney());
        m.work();
        System.out.println("-------------");
        
        //通过构造方法赋值
        m = new Manager("刘意","czbk002",8000,2000);
        System.out.println(m.getName()+"---"+m.getId()+"---"+m.getSalary()+"---"+m.getMoney());
        m.work();
    }
}

多态的成员访问特点及转型的理解

多态的问题理解:
    class 孔子爹 {
        public int age = 40;
        
        public void teach() {
            System.out.println("讲解JavaSE");
        }
    }
    
    class 孔子 extends 孔子爹 {
        public int age = 20;
        
        public void teach() {
            System.out.println("讲解论语");
        }
        
        public void playGame() {
            System.out.println("英雄联盟");
        }
    }
    
    //Java培训特别火,很多人来请孔子爹去讲课,这一天孔子爹被请走了
    //但是还有人来请,就剩孔子在家,价格还挺高。孔子一想,我是不是可以考虑去呢?
    //然后就穿上爹的衣服,带上爹的眼睛,粘上爹的胡子。就开始装爹
    //向上转型
    孔子爹 k爹 = new 孔子();
    //到人家那里去了
    System.out.println(k爹.age); //40
    k爹.teach(); //讲解论语
    //k爹.playGame(); //这是儿子才能做的
    
    
    //讲完了,下班回家了
    //脱下爹的装备,换上自己的装备
    //向下转型
    孔子 k = (孔子) k爹; 
    System.out.println(k.age); //20
    k.teach(); //讲解论语
    k.playGame(); //英雄联盟
    

多态继承中的内存图解

 


多态中的对象变化内存图解

 

4:接口(掌握)
    (1)回顾猫狗案例,它们仅仅提供一些基本功能。
       比如:猫钻火圈,狗跳高等功能,不是动物本身就具备的,
       是在后面的培养中训练出来的,这种额外的功能,java提供了接口表示。
    (2)接口的特点:
        A:接口用关键字interface修饰
            interface 接口名 {}
        B:类实现接口用implements修饰
            class 类名 implements 接口名 {}
        C:接口不能实例化
        D:接口的实现类
            a:是一个抽象类。
            b:是一个具体类,这个类必须重写接口中的所有抽象方法。
    (3)接口的成员特点:
        A:成员变量
            只能是常量
            默认修饰符:public static final
        B:构造方法
            没有构造方法
        C:成员方法
            只能是抽象的
            默认修饰符:public abstract
    (4)类与类,类与接口,接口与接口
        A:类与类
            继承关系,只能单继承,可以多层继承
        B:类与接口
            实现关系,可以单实现,也可以多实现。
            还可以在继承一个类的同时,实现多个接口
        C:接口与接口
            继承关系,可以单继承,也可以多继承
    (5)抽象类和接口的区别(自己补齐)?
        A:成员区别
            抽象类:
            接口:
        B:关系区别:
            类与类:
            类与接口:
            接口与接口:
        C:设计理念不同
            抽象类:is a,抽象类中定义的是共性功能。
            接口:like a,接口中定义的是扩展功能。
    (6)练习:
        A:猫狗案例,加入跳高功能
        B:老师和学生案例,加入抽烟功能0

InterfaceDemo.java

/*
    接口的特点:
        A:接口用关键字interface表示    
            interface 接口名 {}
        B:类实现接口用implements表示
            class 类名 implements 接口名 {}
        C:接口不能实例化
            那么,接口如何实例化呢?
            按照多态的方式来实例化。
        D:接口的子类
            a:可以是抽象类。但是意义不大。
            b:可以是具体类。要重写接口中的所有抽象方法。(推荐方案)
    
    由此可见:
        A:具体类多态(几乎没有)
        B:抽象类多态(常用)
        C:接口多态(最常用)
*/
//定义动物培训接口
interface AnimalTrain {
    public abstract void jump();
}

//抽象类实现接口
abstract class Dog implements AnimalTrain {
}

//具体类实现接口
class Cat implements AnimalTrain {
    public void jump() {
        System.out.println("猫可以跳高了");
    }
}

class InterfaceDemo {
    public static void main(String[] args) {
        //AnimalTrain是抽象的; 无法实例化
        //AnimalTrain at = new AnimalTrain();
        //at.jump();
        
        AnimalTrain at = new Cat();
        at.jump();
    }
}

InterfaceDemo2.java

/*
    接口成员特点
        成员变量;只能是常量,并且是静态的。
                默认修饰符:public static final
                建议:自己手动给出。
        构造方法:接口没有构造方法。
        成员方法:只能是抽象方法。
                默认修饰符:public abstract
                建议:自己手动给出。
        
    所有的类都默认继承自一个类:Object。
    类 Object 是类层次结构的根类。每个类都使用 Object 作为超类。
*/
interface Inter {
    public int num = 10;
    public final int num2 = 20;
    public static final int num3 = 30;
    
    //错误: 需要<标识符>
    //public Inter() {}
    
    //接口方法不能带有主体
    //public void show() {}

    //abstract void show(); //默认public
    public void show(); //默认abstract
}

//接口名+Impl这种格式是接口的实现类格式
/*
class InterImpl implements Inter {
    public InterImpl() {
        super();
    }
}
*/

class Father
{
    public int num = 100;
}

class InterImpl extends Father implements Inter {
    public InterImpl() {
        super();
    }
    
    public void show() {}
}

//测试类
class InterfaceDemo2 {
    public static void main(String[] args) {
        //创建对象
        Inter i = new InterImpl();
        System.out.println(i.num);
        System.out.println(i.num2);
        //i.num = 100;
        //i.num2 = 200;
        //System.out.println(i.num); //无法为最终变量num分配值
        //System.out.println(i.num2);//无法为最终变量num2分配值
        System.out.println(Inter.num);
        System.out.println(Inter.num2);
        System.out.println("--------------");

        InterImpl ii = new InterImpl();

        //System.out.println(ii.num);
        //InterfaceDemo2.java:68: 错误: 对num的引用不明确, Father中的变量 num和Inter中的变量 num都匹配

    }
}

InterfaceDemo3.java

/*
    类与类:
        继承关系,只能单继承,可以多层继承。
    类与接口:
        实现关系,可以单实现,也可以多实现。
        并且还可以在继承一个类的同时实现多个接口。
    接口与接口:
        继承关系,可以单继承,也可以多继承。
*/
interface Father {
    public abstract void show();
}

interface Mother {
    public abstract void show2();
}

interface Sister extends Father,Mother {

}

//class Son implements Father,Mother //多实现
class Son extends Object implements Father,Mother {
    public void show() {
        System.out.println("show son");
    }
    
    public void show2() {
        System.out.println("show2 son");
    }
}

class InterfaceDemo3 {
    public static void main(String[] args) {
        //创建对象
        Father f = new Son();
        f.show();
        //f.show2(); //报错
    
        Mother m = new Son();
        //m.show(); //报错
        m.show2();
    }
}

InterfaceTest.java

/*
    猫狗案例,加入跳高的额外功能
    
    分析:从具体到抽象
        猫:
            姓名,年龄
            吃饭,睡觉
        狗:
            姓名,年龄
            吃饭,睡觉
            
        由于有共性功能,所以,我们抽取出一个父类:
        动物:
            姓名,年龄
            吃饭();
            睡觉(){}
            
        猫:继承自动物
        狗:继承自动物
        
        跳高的额外功能是一个新的扩展功能,所以我们要定义一个接口
        接口:
            跳高
            
        部分猫:实现跳高
        部分狗:实现跳高
    实现;
        从抽象到具体
        
    使用:
        使用具体类
*/
//定义跳高接口
interface Jumpping {
    //跳高功能
    public abstract void jump();
}

//定义抽象类
abstract class Animal {
    //姓名
    private String name;
    //年龄
    private int age;
    
    public Animal() {}
    
    public Animal(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 abstract void eat();
    
    //睡觉(){}
    public void sleep() {
        System.out.println("睡觉觉了");
    }
}

//具体猫类
class Cat extends Animal {
    public Cat(){}
    
    public Cat(String name,int age) {
        super(name,age);
    }
    
    public void eat() {
        System.out.println("猫吃鱼");
    }
}

//具体狗类
class Dog extends Animal {
    public Dog(){}
    
    public Dog(String name,int age) {
        super(name,age);
    }
    
    public void eat() {
        System.out.println("狗吃肉");
    }
}

//有跳高功能的猫
class JumpCat extends Cat implements Jumpping {
    public JumpCat() {}
    
    public JumpCat(String name,int age) {
        super(name,age);
    }

    public void jump() {
        System.out.println("跳高猫");
    }
}

//有跳高功能的狗
class JumpDog extends Dog implements Jumpping {
    public JumpDog() {}
    
    public JumpDog(String name,int age) {
        super(name,age);
    }

    public void jump() {
        System.out.println("跳高狗");
    }
}

class InterfaceTest {
    public static void main(String[] args) {
        //定义跳高猫并测试
        JumpCat jc = new JumpCat();
        jc.setName("哆啦A梦");
        jc.setAge(3);
        System.out.println(jc.getName()+"---"+jc.getAge());
        jc.eat();
        jc.sleep();
        jc.jump();
        System.out.println("-----------------");
        
        JumpCat jc2 = new JumpCat("加菲猫",2);
        System.out.println(jc2.getName()+"---"+jc2.getAge());
        jc2.eat();
        jc2.sleep();
        jc2.jump();
        
        //定义跳高狗并进行测试的事情自己完成。
    }
}

InterfaceTest2.java

/*
    老师和学生案例,加入抽烟的额外功能
    
    分析:从具体到抽象
        老师:姓名,年龄,吃饭,睡觉
        学生:姓名,年龄,吃饭,睡觉
        
        由于有共性功能,我们提取出一个父类,人类。
        
        人类:
            姓名,年龄
            吃饭();
            睡觉(){}
            
        抽烟的额外功能不是人或者老师,或者学生一开始就应该具备的,所以,我们把它定义为接口
        
        抽烟接口。

        部分老师抽烟:实现抽烟接口
        部分学生抽烟:实现抽烟接口
        
    实现:从抽象到具体
        
    使用:具体
*/
//定义抽烟接口
interface Smoking {
    //抽烟的抽象方法
    public abstract void smoke();
}

//定义抽象人类
abstract 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 abstract void eat();
    
    //睡觉(){}
    public void sleep() {
        System.out.println("睡觉觉了");
    }
}

//具体老师类
class Teacher extends Person {
    public Teacher() {}
    
    public Teacher(String name,int age) {
        super(name,age);
    }
    
    public void eat() {
        System.out.println("吃大白菜");
    }
}

//具体学生类
class Student extends Person {
    public Student() {}
    
    public Student(String name,int age) {
        super(name,age);
    }
    
    public void eat() {
        System.out.println("吃红烧肉");
    }
}

//抽烟的老师
class SmokingTeacher extends Teacher implements Smoking {
    public SmokingTeacher() {}
    
    public SmokingTeacher(String name,int age) {
        super(name,age);
    }

    public void smoke() {
        System.out.println("抽烟的老师");
    }
}

//抽烟的学生
class SmokingStudent extends Student implements Smoking {
    public SmokingStudent() {}
    
    public SmokingStudent(String name,int age) {
        super(name,age);
    }

    public void smoke() {
        System.out.println("抽烟的学生");
    }
}

class InterfaceTest2 {
    public static void main(String[] args) {
        //测试学生
        SmokingStudent ss = new SmokingStudent();
        ss.setName("林青霞");
        ss.setAge(27);
        System.out.println(ss.getName()+"---"+ss.getAge());
        ss.eat();
        ss.sleep();
        ss.smoke();
        System.out.println("-------------------");
        
        SmokingStudent ss2 = new SmokingStudent("刘意",30);
        System.out.println(ss2.getName()+"---"+ss2.getAge());
        ss2.eat();
        ss2.sleep();
        ss2.smoke();
        
        //测试老师留给自己练习
    }
}

抽象类和接口的区别

抽象类和接口的区别:
A:成员区别
    抽象类:
        成员变量:可以变量,也可以常量
        构造方法:有
        成员方法:可以抽象,也可以非抽象
    接口:
        成员变量:只可以常量
        成员方法:只可以抽象
        
B:关系区别
    类与类
        继承,单继承
    类与接口
        实现,单实现,多实现
    接口与接口
        继承,单继承,多继承
        
C:设计理念区别
    抽象类 被继承体现的是:”is a”的关系。抽象类中定义的是该继承体系的共性功能。
    接口 被实现体现的是:”like a”的关系。接口中定义的是该继承体系的扩展功能。

 

posted on 2015-10-12 23:19  super90  阅读(158)  评论(0编辑  收藏  举报

导航