JAVA基础【day08】:面向对象(3)

这辈子没办法做太多事情,所以每一件都要做到精彩绝伦。 --------史蒂夫.乔布斯

关键字(final)

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

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();
    }
}
/*
    面试题: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();
    }
}

多态

(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:老师和学生案例
/*
    看程序写结果:先判断有没有问题,如果没有,写出结果
    
    多态的成员访问特点:
        方法:编译看左边,运行看右边。
        
    继承的时候:
        子类中有和父类中一样的方法,叫重写。
        子类中没有父亲中出现过的方法,方法就被继承过来了。
*/
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();
    }
}

多态的问题理解

多态的问题理解:
    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(); //英雄联盟
    

抽象类

(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 无意义
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();
    }
}
/*
    假如我们在开发一个系统时需要对员工类进行设计,员工包含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("-------------");
         
        //由于子类有特有的内容,所以我们用子类来测试
        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();
    }
}

接口

(1)回顾猫狗案例,它们仅仅提供一些基本功能。
      比如:猫钻火圈,狗跳高等功能,不是动物本身就具备的,
      是在后面的培养中训练出来的,这种额外的功能,java提供了接口表示。
(2)接口的特点:
    A:接口用关键字interface修饰
        interface 接口名 {}
    B:类实现接口用implements修饰
        class 类名 implements 接口名 {}
    C:接口不能实例化
    D:接口的实现类
        a:是一个抽象类。
        b:是一个具体类,这个类必须重写接口中的所有抽象方法。\
    由此可见:
        A:具体类多态(几乎没有)
        B:抽象类多态(常用)
        C:接口多态(最常用)
(3)接口的成员特点:
    A:成员变量
        只能是常量
        默认修饰符:public static final
    B:构造方法
        没有构造方法
    C:成员方法
        只能是抽象的
        默认修饰符:public abstract
(4)类与类,类与接口,接口与接口
    A:类与类
        继承关系,只能单继承,可以多层继承
    B:类与接口
        实现关系,可以单实现,也可以多实现。
        还可以在继承一个类的同时,实现多个接口
    C:接口与接口
        继承关系,可以单继承,也可以多继承
(5)抽象类和接口的区别:
    A:成员区别
        抽象类:
            成员变量:可以变量,也可以常量
            构造方法:有
            成员方法:可以抽象,也可以非抽象
        接口:
            成员变量:只可以常量
            成员方法:只可以抽象
    B:关系区别
        类与类
            继承,单继承
        类与接口
            实现,单实现,多实现
        接口与接口
            继承,单继承,多继承
    C:设计理念区别
        抽象类 被继承体现的是:”is a”的关系。抽象类中定义的是该继承体系的共性功能。
        接口 被实现体现的是:”like a”的关系。接口中定义的是该继承体系的扩展功能。
//定义动物培训接口
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();
    }
}
/*
    老师和学生案例,加入抽烟的额外功能
    
    分析:从具体到抽象
        老师:姓名,年龄,吃饭,睡觉
        学生:姓名,年龄,吃饭,睡觉
        
        由于有共性功能,我们提取出一个父类,人类。
        
        人类:
            姓名,年龄
            吃饭();
            睡觉(){}
            
        抽烟的额外功能不是人或者老师,或者学生一开始就应该具备的,所以,我们把它定义为接口
        
        抽烟接口。

        部分老师抽烟:实现抽烟接口
        部分学生抽烟:实现抽烟接口
        
    实现:从抽象到具体
        
    使用:具体
*/
//定义抽烟接口
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("小源同学",20);
        System.out.println(ss2.getName()+"---"+ss2.getAge());
        ss2.eat();
        ss2.sleep();
        ss2.smoke(); 
    }
}

你可能感兴趣的:(JAVA基础【day08】:面向对象(3))