10、面向对象(抽象类、接口)

抽象类

复习

package org.westos.demo;

/**
 * @author lwj
 * @date 2020/4/20 16:46
 */
public class MyDemo {
    public static void main(String[] args) {
        Panda panda = new Panda();
        //抽象类AbstractAnimal初始化
        //Panda构造方法执行了
        System.out.println(panda.num);
        //20
    }
}

abstract class AbstractAnimal {

    /** 抽象类不能直接实例化,但是抽象类存在构造方法,目的是子类在创建对象时需要初始化父类(抽象类)的数据 */
    public AbstractAnimal() {
        System.out.println("抽象类AbstractAnimal初始化");
        //1
    }

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

    /**
     * 抽象方法eat
     */
    protected abstract void eat();
}

class Panda extends AbstractAnimal {
    {
        num = 20;
    }
    int num;

    public Panda() {
        System.out.println("Panda构造方法执行了");
        //2
    }

    @Override
    protected void eat() {
        System.out.println("大熊猫吃竹子");
    }
}

class Cat extends AbstractAnimal {

    public Cat() {
        System.out.println("Cat构造方法执行了");
    }

    @Override
    protected void eat() {
        System.out.println("猫咪吃小鱼干");
    }
}

抽象类的成员特点

  • 成员变量:既可以是变量,也可以是常量
  • 构造方法:存在,用于子类创建对象时初始化父类数据
  • 成员方法:既可以是抽象的,也可以是非抽象的。
    • 抽象方法:强制子类实现抽象方法
    • 非抽象方法:子类可以重写父类的方法,也可以不重写父类的方法
package org.westos.demo;

/**
 * @author lwj
 * @date 2020/4/20 17:14
 */
public class MyDemo2 {
    public static void main(String[] args) {
        Student student = new Student(2);
        System.out.println(student.nation);
        //中国
        student.show();
        //我是父类
        //子类重写父类的show()方法
        student.abstractMethod();
        //我是子类
    }
}

abstract class AbstractPerson {
    public int id = 1;

    /** final类型变量在定义后,1、在定义声明时初始化,2、在构造代码块中初始化,3、在构造方法中初始化 */
    public final String nation;

    {
        nation = "中国";
    }

    public AbstractPerson(int id) {
        this.id = id;
    }
    /** 抽象方法 */
    public abstract void abstractMethod();

    public void show() {
        System.out.println("我是父类");
    }
}

class Student extends AbstractPerson {

    /*由于父类的构造方法只有一个有参构造,而子类默认无参构造,调用父类的无参构造失败,所以报错,
      解决:子类生成一个有参构造,并且显式调用父类有参构造 */

    public Student(int id) {
        super(id);
    }

    @Override
    public void abstractMethod() {
        System.out.println("我是子类");
    }

    @Override
    public void show() {
        super.show();
        System.out.println("子类重写父类的show()方法");
    }
}

抽象类中的面试题

1、一个类如果没有抽象方法,可不可以定义为抽象类?如果可以,有什么意义?

可以,不能创建该类对象。

2、abstract不能和哪些关键字共存?

  1. abstract修饰方法,子类必须重写该方法,private修饰方法,子类无法继承,则不能重写,所以冲突;

  2. abstract修饰类,代表抽象类,子类继承抽象类,与final(修饰类,所修饰的类不能被继承)冲突;

  3. abstract修饰方法,代表抽象类中的抽象方法,子类继承抽象类,必须实现抽象类中的抽象方法,和final(修饰方法,所修饰的方法不能被子类重写)冲突;

  4. abstract修饰方法,代表抽象方法,没有方法体,static修饰方法代表静态方法,有方法体,不参与重写,不能共存,无意义。

接口

接口的特点

  • 接口使用关键字interface表示,interface 接口名 {}
  • 类实现接口使用关键字implements表示,class 类名 implements 接口名 {}
  • 接口不能实例化,按照多态的方式实例化
  • 接口的子类
    • 抽象类,abstract class 类名 implements 接口名 {}
    • 具体类,要重写接口中的所有抽象方法,class 类名 implements 接口名 {}
package org.westos.demo2;

/**
 * @author lwj
 * @date 2020/4/20 17:33
 */
public class MyDemo {
}

interface IExpandMethod {
    /**
     * 打电话
     */
    public abstract void call();
}

abstract class AbstractAnimal implements IExpandMethod {

}

class Animal implements IExpandMethod {

    @Override
    public void call() {
        System.out.println("具体类必须实现接口中所有方法");
    }
}

接口的成员特点

  • 成员变量:只能是常量,并且是public static的,默认修饰符:public static final
  • 构造方法:接口中没有构造方法
  • 成员方法:只能是抽象方法,默认修饰符:public abstract

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

  • 类与类:继承关系,只能单继承,可以多层继承;
  • 类与接口:实现关系,可以单实现,也可以多实现,多个接口之间用,隔开,并且可以在继承一个类的同时实现多个接口;
  • 接口与接口:继承关系,可以单继承,也可以多继承。
//类与类:extends,单继承
//类与接口:implements,单实现,多实现
public final class Integer extends Number implements Comparable<Integer> {}
public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable{}
//接口与接口:extends,单继承,多继承
public interface List<E> extends Collection<E> {}
public interface SortedMap<K,V> extends Map<K,V> {}

抽象类与接口的区别

成员区别:

  • 抽象类:
    • 成员变量:可以变量,可以常量
    • 构造方法:存在构造方法
    • 成员方法:可以抽象,可以非抽象
  • 接口:
    • 成员变量:只可以常量
    • 构造方法:不存在构造方法
    • 成员方法:只可以抽象

关系区别:

  • 类与类
    • 继承,单继承
  • 类与接口
    • 实现,单实现,多实现
  • 接口与接口
    • 继承,单继承,多继承

设计理念的区别:

  • 抽象类
    • 被继承体现的是"is a"的关系,抽象类中定义的是该继承体类的共性功能
  • 接口
    • 被实现体现的是"like a"的关系,接口中定义的是该继承体系的扩展功能

注意:JDK 1.8之后在接口中提供了用default修饰的方法,可以给出功能的具体实现,子类可以继承下去用。

package org.westos.demo3;

/**
 * @author lwj
 * @date 2020/4/20 20:09
 */
public interface IExpandMethod {
    int NUMBER = 10;

    /**
     * 1、jdk1.7 公共静态常量和public abstract抽象方法
     * 钻火圈
     */
    void fire();

    /**
     * 2、jdk1.8 增加default关键字修饰方法,可以存在方法体,默认权限修饰符为public
     * 展示
     */
    default void show() {
        System.out.println("展示");
    }

    /**
     * 3、jdk1.8 增加static静态方法,默认权限修饰符为public
     * 测试
     */
    static void test() {
        System.out.println("静态方法");
    }
}

class ExpandMethodImpl implements IExpandMethod {

    @Override
    public void fire() {
        System.out.println("钻火圈");
    }
}

class MyDemo {
    public static void main(String[] args) {
        IExpandMethod test = new ExpandMethodImpl();
        test.fire();
        //钻火圈
        test.show();
        //展示
        System.out.println(IExpandMethod.NUMBER);
        //10
        IExpandMethod.test();
        //静态方法
    }
}

抽象类与接口的练习

抽象类

package org.westos.demo3;

/**
 * @author lwj
 * @date 2020/4/20 20:36
 */
public abstract class Animal {
    public String name;
    public int age;

    /**
     * 吃饭
     */
    public abstract void eat();

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

实现类

package org.westos.demo3;

/**
 * @author lwj
 * @date 2020/4/20 20:38
 */
public class Cat extends Animal{
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }

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

扩展功能

package org.westos.demo3;

/**
 * 扩展功能
 * @author lwj
 * @date 2020/4/20 20:42
 */
public interface IHighJump {
    /**
     * 动物跳高
     */
    void highJump();
}

加菲猫

package org.westos.demo3;

/**
 * 加菲猫
 * @author lwj
 * @date 2020/4/20 20:40
 */
public class Garfield extends Cat implements IHighJump{
    @Override
    public void eat() {
        System.out.println("加菲猫吃鱼排");
    }

    @Override
    public void sleep() {
        System.out.println("加菲猫睡在沙发上");
    }

    @Override
    public void highJump() {
        System.out.println("加菲猫学会了跳高");
    }
}

狸花猫

package org.westos.demo3;

/**
 * 狸花猫
 * @author lwj
 * @date 2020/4/20 20:44
 */
public class CivetCat extends Cat {
    @Override
    public void eat() {
        System.out.println("狸花猫吃鱼翅");
    }

    @Override
    public void sleep() {
        System.out.println("狸花猫睡在摇篮里");
    }
    
    public void catchMouse() {
        System.out.println("狸花猫抓老鼠");
    }
}

测试方法

package org.westos.demo3;

/**
 * @author lwj
 * @date 2020/4/20 20:46
 */
public class MyTest {
    public static void main(String[] args) {
        Garfield garfield = new Garfield();
        Cat cat = garfield;
        cat.name = "波斯猫";
        cat.age = 2;
        cat.eat();
        cat.sleep();
        IHighJump jump = garfield;
        jump.highJump();
        System.out.println("===============");
        CivetCat civetCat = new CivetCat();
        cat = civetCat;
        cat.name = "狸花猫";
        cat.age = 3;
        cat.eat();
        cat.sleep();
        CivetCat civetCat1 = (CivetCat) cat;
        //执行CivetCat的特有方法,需要向下转型
        civetCat1.catchMouse();
    }
}

猜你喜欢

转载自www.cnblogs.com/shawnyue-08/p/12740529.html