JAVASE第9天笔记

Day09课堂笔记

标签(空格分隔): java基础


多态

  • 多态:事物的多种形态
  • 多态的前提条件是什么?
    1,要有继承关系(extends关键字,让类和类之间产生关系)
    2,要有方法重写(子父类中,出现一模一样的方法,返回值可以是子父类)
    3,父类的引用指向了子类对象(父类引用 ? 父类类名 对象名(引用) 子类对象 : new 子类类名()) 书写在测试类中
    举例:
class Father {  //父类
    String name;
    public void show(){
        System.out.println("父类的方法");
    }
}
class Son extends Father{  //子类 这是第一个条件
    //这是第二个条件
    public void show(){
        System.out.println("子类的方法");
    }
}
class Test{
    public static void main(String[] args){
        //第三个条件
        Father f = new Son();
    }
}

多态中成员变量的访问特点是什么?

特点: 编译看左边 ,运行看左边 (左边:父类 右边:子类)
举例 Father f = new Son(); //这是多态,左边指的是父类 右边指的是子类
Son s = new Son(); //这不是多态
成员变量: 子父类中存在一模一样的成员变量的时候,这个时候去访问,就有编译看左边,运行看左边的特点
举例

class Father {  //父类
    String name = "父类";
}
class Son extends Father{  //子类 这是第一个条件
    String name = "子类";
}
class Test{
    public static void main(String[] args){
        Father f = new Son();
        System.out.println(f.name); //子父类中都有的成员变量
    }
}

注意:这种写法开发中不用,只是说明有这个特点

多态中成员方法的访问特点

编译看左边,运行看右边
如果说,父类里面没有这个方法,而子类中有,这个时候如果我用父类的引用调用子类的对象的时候,会怎样? 报错
如果说,父类里面有这个方法,而子类并没有重写,这个时候用父类的引用调用这个方法,又会怎样?
如果没有方法重写,你如果达到了继承和父类引用指向子类对象,这也是多态一种,但是没有意义!

class Demo_Duotai {
    public static void main(String[] args) {
        //如果没有方法重写,这样就失去多态的意义
        Father f = new Son();
        //编译看左边,运行看右边
        f.show(); 

        Son s = new Son();
        s.show();
    }
}

class Father
{
    public void show(){
        System.out.println("父类的show方法");
    }
}
class Son extends Father
{
    //子类实际上是有,这个方法是从父类里面继承过来的
}

多态中静态成员方法的访问特点

  • 编译看父类(左边),运行的时候也是看父类(左边)

多态中三个成员访问特点总结

区别编译运行
成员变量左边(父类)左边父类
普通成员方法左边(父类)右边(子类)
静态成员方法左边(父类)左边

多态中父类的引用调用子类的特有方法出现编译的问题

思考:如何解决? 在使用的时候,父类的引用调用子类特有方法调用不了.

class Demo3_SuperMan {
    public static void main(String[] args) {
        //第三个条件 父类的引用指向子类对象  格式: 父类 对象名 = new 子类()
        Person p = new SuperMan();          //父类引用指向子类对象,超人提升为了人
                                            //父类引用指向子类对象就是向上转型
        System.out.println(p.name);
        p.谈生意();
        //在我们使用子类的方法时候,发现了一个多态的问题,问题是子类的方法如果不是重写了父类的,父类里面没有这个方法,编译报错,没法通过
        //这个时候怎么才能让这个编译通过呢? 解决方法?
        p.fly();  //编译看左边(父类) ,问题是父类没有fly方法 编译报出以下错误:Demo3_SuperMan.java:8: 错误: 找不到符号
    }
}

class Person {  // 父类
    String name = "John";
    public void 谈生意() {  //第二个条件 父类有谈生意方法
        System.out.println("谈生意");
    }
}

class SuperMan extends Person { //子类  多态:第一个条件 要有继承关系
    String name = "superMan";

    public void 谈生意() { //第二个条件满足 有方法重写
        System.out.println("谈几个亿的大单子"); ///方法体可以不一样
    }

    public void fly() {
        System.out.println("飞出去救人");
    }
}

向上转型和向下转型

向上转型:父类的引用指向了子类对象 Father f = new Son();
向下转型的前提:必须要有向上转型
向下转型:格式 子类 对象名 = (子类类名)父类的引用Son s = (Son)f;
你会怎么想?
通过观察,我们发现了一个问题,其实来来去去无非调用的都是子类的方法,这个时候其实我们可以直接创建一个子类对象出来,直接调用方法,根本不需要用父类的引用指向子类对象,然后再用父类转型回子类调用子类特有方法.
思考?为什么要这么做?

多态的好处和弊端分别是什么?

多态的好处:提高代码扩展性
应用场景:在调用方法的时候,作为参数传递,这个时候我们可以节省书写代码演示好处

案例(非常非常非常重要)

class Demo4_Animal {
    public static void main(String[] args) {
        //需求: 让你调用猫类的吃方法 和狗类的吃方法
        //需求改变:让你调用1000个猫的吃方法,和多个狗的吃方法
        //解决方法:如果要调用同样的方法 这个时候,我想 能否帮我封装一个方法出来,我只要给你传对象,你就帮我调用方法
        //需求升级:调用猪鸭鹅鸡羊牛.......的吃方法
        /*Cat c1 = new Cat()
        c1.eat();
        Cat c2= new Cat()
        c2.eat();
        Cat c3 = new Cat()
        c3.eat();
        Cat c1 = new Cat()
        c1.eat();
        Cat c2= new Cat()
        c2.eat();
        Cat c3 = new Cat()
        c3.eat();
        Cat c1 = new Cat()
        c1.eat();
        Cat c2= new Cat()
        c2.eat();
        Cat c3 = new Cat()
        c3.eat();
        Cat c1 = new Cat()
        c1.eat();
        Cat c2= new Cat()
        c2.eat();
        Cat c3 = new Cat()
        c3.eat();
        ...*/
        show(new Cat());
        show(new Cat());
        show(new Cat());
        show(new Dog());
        show(new Dog());
        show(new Dog());
        show(new Zhu());
        show(new Zhu());
        show(new Zhu());
        show(new Ya());
        show(new Ya());
        show(new Ya());

    }
    //自从用了方法之后啊,我们发现,不用不断的创建对象,然后一个个调用eat方法,现在的好处是:直接把这个对象放进去方法,就可以帮我直接调用eat方法,我们就不需要手动去调用eat方法

    //没用多态前
    /*
    public static void show(Cat c){
        c.eat();
    }
    public static void show(Dog d){
        d.eat();
    }
    public static void show(Zhu z){
        z.eat();
    }
    public static void show(Ya y){
        y.eat();
    }
    public static void show(Niu z){
        z.eat();
    }
    public static void show(Ji y){
        y.eat();
    }*/
    //用了多态后
    public static void show(Animal a){
        a.eat();  //都是为了调用公用的方法,也就是重写方法
    }
    //如果把狗强转成猫就会出现类型转换异常,ClassCastException
    public static void method(Animal a) {   //当作参数的时候用多态最好,因为扩展性强
        //关键字 instanceof 判断前边的引用是否是后边的数据类型
        if (a instanceof Cat) {
            Cat c = (Cat)a;
            c.eat();
            c.catchMouse();
        }else if (a instanceof Dog) {
            Dog d = (Dog)a;
            d.eat();
            d.lookHome();
        }else {
            a.eat();
        }
    }
}
/*
* A:多态的好处
    * a:提高了代码的维护性(继承保证)
    * b:提高了代码的扩展性(由多态保证)
* B:案例演示
    * 多态的好处
    * 可以当作形式参数,可以接收任意子类对象
* C:多态的弊端
    * 不能使用子类的特有属性和行为。
*/

class Animal {
    public void eat() {  //第二个 方法
        System.out.println("动物吃饭");
    }
}

class Cat extends Animal { //第一个条件 继承
    public void eat() { //方法重写
        System.out.println("猫吃鱼");
    }

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

class Dog extends Animal { //第一个条件 符合继承要求
    public void eat() { //第二个条件 方法的重写
        System.out.println("狗吃肉");
    }

    public void lookHome() {
        System.out.println("看家");
    }
}
class Zhu extends Animal { //第一个条件 符合继承要求
    public void eat() { //第二个条件 方法的重写
        System.out.println("猪吃米");
    }

    public void sleep() {
        System.out.println("睡觉");
    }
}
class Ya extends Animal { //第一个条件 符合继承要求
    public void eat() { //第二个条件 方法的重写
        System.out.println("鸭吃鸭粮...");
    }

    public void sleepWithSomeBody() {
        System.out.println("陪动物睡觉");
    }
}

抽象类

抽象类的特点有哪些?
什么是抽象类 用abstract关键字修饰的类就是抽象类
1,抽象类里面 可以有抽象方法 也可以没有抽象方法
2,如果这个类有抽象方法那么这个必然是抽象类/接口
3,抽象方法没有方法体 public abstract void eat();
4,抽象类是不能实例化,也就是说不能直接new对象,如果要new对象怎么办?只能用父类的引用指向子类的对象.
5,如果一个类继承了抽象类,那么这个类要么是抽象类,要么就重写抽象类里面的所有抽象方法

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

举例

class Cat extends Animal{
    //继承了抽象类,就必须把这个抽象类里面的抽象方法重写
    public void sleep(){
        System.out.println("这是猫的睡觉方式");
    }
}

这个方法体谁来实现? 子类来实现

  • 抽象类中的成员特点是什么?
  • 成员变量:可以是变量或者常量
  • 构造方法: 有,给子类进行初始化
  • 成员方法 : 可以是普通成员方法或者抽象的成员方法

  • 抽象方法的作用是什么?
    强制子类重写这个方法

猫狗类案例

⦁ 思考:一个抽象类如果没有抽象方法,可不可以定义为抽象类?如果可以,有什么意义?

可以,目的:不让你直接new 这个类的对象,只能让你new它子类对象
abstract class Demo{
}
抽象类abstract关键字不能和什么关键字共存?
static final private

关于接口

接口: 其实就是一种规则 java 里interface表示接口
广义角度:规则,举例 USB接口,符合USB2.0规范
开发中说法:书写接口:书写功能模块,对外提供访问方式

接口用哪个关键字表示?
interface 定义接口的关键字
类实现接口用哪个关键字?
implements 实现的关键字

interface Inter{ //接口名也是标识符,你自己起的名字
    //抽象方法...
}
class Demo implements Inter{
    //把接口的抽象方法全部实现
}

接口的成员特点是什么?

成员变量:只能是常量,不能是变量,并且是静态的,公共的,最终的
默认 public static final
构造方法:没有
成员方法:只能是的抽象成员方法 public abstract ,如果不写就默认给你加上
举例:

interface Inter{
    //手动给出
    public static final String name = "xxx";
    String name = "yyy"; //系统也默认给你写上
    //方法
    public abstract void add(); //手动书写 public abstract
    void remove(); //系统也默认给你书写上
}

类与类,类与接口,接口与接口的关系分别是什么?
类和类 :继承关系,只能单继承,不能多继承 ,用extends关键字
类和接口:实现关系,implements关键字 ,可以多实现
接口和接口:继承,可以多继承,用extends关键
举例

interface A{
}
//正确书写
interface B extends A{
}
//错误书写
interface B implements A{
}
//正确书写
interface C extends A,B{ //接口支持多继承
}

接口和抽象类的区别

区别接口抽象类
成员变量常量变量/常量
构造方法没有有,给子类初始化
成员方法抽象抽象/抽象
设计理念like a,像什么的一种,一般作为扩展功能is a 是什么的一种,一般就是继承共性功能

现在要求: 怎么写一个接口,怎么用一个类去实现一个接口?用什么关键字!

案例 (非常非常重要)

class Test1_Animal {
    public static void main(String[] args) {
        Cat c = new Cat("加菲",8);
        c.eat();
        c.sleep();

        JumpCat jc = new JumpCat("跳高猫",3);
        jc.eat();
        jc.sleep();
        jc.jump();
    }
}

/*
* A:案例演示
    * 动物类:姓名,年龄,吃饭,睡觉。
    * 猫和狗
    * 动物培训接口:跳高
*/

abstract class Animal {
    private String name;                //姓名
    private int age;                    //年龄

    public Animal() {}                  //空参构造

    public Animal(String name,int age) {//有参构造
        this.name = name;
        this.age = age;
    }

    public void setName(String name) {  //设置姓名
        this.name = name;
    }

    public String getName() {           //获取姓名
        return name;
    }

    public void setAge(int age) {       //设置年龄
        this.age = age;
    }

    public int getAge() {               //获取年龄
        return age;
    }

    public abstract void eat();         //吃饭

    public abstract void sleep();       //睡觉
}

interface Jumping {                     //跳高的接口
    public void jump();
}

class Cat extends Animal {
    public Cat() {}                 //空参构造

    public Cat(String name,int age) {//有参构造
        super(name,age);
    }

    public void eat() {
        System.out.println("猫吃鱼");
    }

    public void sleep() {
        System.out.println("侧着睡");
    }
}

class JumpCat extends Cat implements Jumping {
    public JumpCat() {}                 //空参构造

    public JumpCat(String name,int age) {//有参构造
        super(name,age);
    }

    public void jump() {
        System.out.println("猫跳高");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值