java面向对象编程_包_继承_多态_重载和重写_抽象类_接口_this和super(3)

简介: java面向对象编程_包_继承_多态_重载和重写_抽象类_接口_this和super(3)

接口

基本语法

//定义接口类型
interface IAnimal{
    //抽象方法
    // public static final 字段
}

使用interface 定义一个接口

image.png

接口中的方法一定是抽象方法, 因此可以省略 abstract

接口中的方法一定是public, 因此可以省略public

image.png

接口中只能包含抽象方法,对于字段来说, 接口中只能包含静态常量(final static)

interface IAnimal{
    // public static final 字段 可以省略public static final
    String name = "animal"; //因为是final 修饰,需要赋初值!
    int age = 18;
    //抽象方法
    public abstract void speak();
    void eat(); //省略public abstract
}

子类 使用 implements继承接口。 此时表达的含义不再是 “扩展”, 而是 “实现”


在调用的时候同样可以创建一个接口的引用, 对应到一个子类的实例。


接口不能单独被实例化。


扩展(extends)vs 实现(implements)


扩展指的是当前已经有一定的功能了, 进一步扩充功能。

实现指的是当前啥都没有, 需要从头构造出来。


接口不能用限定符修饰

image.png

实现多个接口

接口弥补了java无法多继承的缺陷!

我们可以实现多个接口

基本语法


有时候我们需要让一个类同时继承自多个父类. 这件事情在有些编程语言通过 多继承 的方式来实现的。然而 Java 中只支持单继承, 一个类只extends 一个父类。 但是可以同时实现多个接口, 也能达到多继承类似的效果。

class 类名 implement interfa1,interface2,....interfaceN{
     //实现所有接口中的方法!
}

实例一

下面我们通过类来表示张三

//实现多个接口
interface IAnimal{
    String name = "animal";
    int age = 18;
    void speak();
    void eat();
}
interface IPeople{
    String iQ = "140";
    void study();
}
class Zhansan implements IAnimal,IPeople{
    @Override
    public void speak() {
        System.out.println("Speak Chinese!");
    }
    @Override
    public void eat() {
        System.out.println("Eat food!");
    }
    @Override
    public void study() {
        System.out.println("Study java!");
    }
}
public class Test_6 {
    public static void main(String[] args) {
        Zhansan zhansan = new Zhansan();
        zhansan.eat();
        zhansan.speak();
        zhansan.study();
    }
}

image.png

实例二

现在我们通过一个类来表示一组动物。

class Animal { 
  protected String name; 
    public Animal(String name) { 
        this.name = name; 
    } 
}

另外我们再提供一组接口, 分别表示 “会飞的”, “会跑的”, “会游泳的”。

interface IFlying { 
    void fly(); 
} 
interface IRunning { 
    void run(); 
} 
interface ISwimming { 
    void swim(); 
}

接下来我们创建几个具体的动物

猫, 是会跑的。

class Cat extends Animal implements IRunning { 
    public Cat(String name) { 
        super(name); 
    } 
    @Override 
    public void run() { 
        System.out.println(this.name + "正在用四条腿跑"); 
    } 
}

image.png


鱼, 是会游的。

class Fish extends Animal implements ISwimming { 
    public Fish(String name) { 
        super(name); 
    } 
    @Override 
    public void swim() { 
        System.out.println(this.name + "正在用尾巴游泳"); 
    } 
}

image.png

青蛙, 既能跑, 又能游(两栖动物)

class Frog extends Animal implements IRunning, ISwimming { 
    public Frog(String name) { 
        super(name);
    } 
    @Override 
    public void run() { 
        System.out.println(this.name + "正在往前跳"); 
    } 
    @Override 
    public void swim() { 
        System.out.println(this.name + "正在蹬腿游泳"); 
    } 
}

image.png

提示,IDEA中使用 ctrl + i 快速实现接口

image.png


还有一种神奇的动物, 水陆空三栖, 叫做 “鸭子”

class Duck extends Animal implements IRunning, ISwimming, IFlying { 
    public Duck(String name) { 
        super(name); 
    } 
    @Override 
    public void fly() { 
        System.out.println(this.name + "正在用翅膀飞"); 
    } 
    @Override 
    public void run() { 
        System.out.println(this.name + "正在用两条腿跑"); 
    } 
    @Override 
    public void swim() { 
        System.out.println(this.name + "正在漂在水上"); 
    } 
}


image.png

上面的代码展示了 Java面向对象编程中最常见的用法: 一个类继承一个父类, 同时实现多种接口。


继承表达的含义是 is - a 语义, 而接口表达的含义是 具有xxx 特性 。


猫是一种动物, 具有会跑的特性。

青蛙也是一种动物, 既能跑, 也能游泳

鸭子也是一种动物, 既能跑, 也能游, 还能飞

这样设计有什么好处呢?


时刻牢记多态的好处, 让程序猿忘记类型. 有了接口之后, 类的使用者就不必关注具体类型, 而只关注某个类是否具备某种能力!


例如, 现在实现一个方法, 叫 “散步”

public static void walk(IRunning running) { 
    System.out.println("我带着伙伴去散步"); 
    running.run(); 
}

在这个walk方法内部, 我们并不关注到底是哪种动物, 只要参数是会跑的, 就行

Cat cat = new Cat("小猫"); 
walk(cat); 
Frog frog = new Frog("小青蛙"); 
walk(frog);


image.png

甚至参数可以不是 “动物”, 只要会跑


class Robot implements IRunning { 
    private String name; 
    public Robot(String name) { 
        this.name = name; 
    } 
    @Override 
    public void run() { 
        System.out.println(this.name + "正在用轮子跑"); 
    } 
} 
Robot robot = new Robot("机器人"); 
walk(robot);

image.png


接口的使用实例

我们java系统包中的很多类都实现了很多接口,使得该类具有某种属性


给对象排序!

//创建student类
class Student{
    private String name;
    private double score;
    public Student(String name,double score){
      this.name = name;
      this.score = score;
    }
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", score=" + score +
                '}';
    }
}
public static void main(String[] args) {
  //学生对象数组
        Student[] students = new Student[]{
                new Student("张三",88.7),
                new Student("李四",67),
                new Student("王五",98),
        };
        Arrays.sort(students); //排序
        System.out.println(students);
    }

显然,我们无法排序对象类型的数据,

报异常,说我们Student类没有实现Comparable接口!

image.png

Comparable接口中的抽象方法 compareTo

方法详细信息


int compareTo(T o)将此对象与指定的对象进行比较以进行排序。 返回一个负整数,零或正整数,因为该对象小于,等于或大于指定对象。


实现程序必须确保sgn(x.compareTo(y)) == -sgn(y.compareTo(x))所有x和y。 (这意味着x.compareTo(y)必须抛出异常if y.compareTo(x)引发异常。)


实施者还必须确保关系是可传递的: (x.compareTo(y)>0 && y.compareTo(z)>0)表示x.compareTo(z)>0。


最后,实施者必须确保x.compareTo(y)==0意味着sgn(x.compareTo(z)) == sgn(y.compareTo(z)) ,对于所有z 。


强烈建议,但不要严格要求(x.compareTo(y)==0) == (x.equals(y)) 。 一般来说,任何实现Comparable接口并违反这种情况的类应清楚地表明这一点。 推荐的语言是“注意:此类具有与equals不一致的自然排序”。


在前面的描述中,符号sgn( ) 表达式表示数学符号函数,其定义根据表达式的值是否为负,零或正返回的-1一个,0,或1。


参数

o -要比较的对象。

结果

负整数,零或正整数,因为该对象小于,等于或大于指定对象。

异常

NullPointerException- 如果指定的对象为空

ClassCastException- 如果指定的对象的类型阻止它与该对象进行比较。


看到这么多文字,是不是头都大了!

没有关系,bug郭也头大,不过我知道咋用

//创建student类并且实现Comparable接口
class Student implements Comparable{
    private String name;
    private double score;
    public Student(String name,double score){
      this.name = name;
      this.score = score;
    }
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", score=" + score +
                '}';
    }
    @Override  //实现compareTo方法
    public int compareTo(Object o) {
        Student s = (Student)o; //对o强转, o指的是待比较对象
        if (this.score > s.score) {    //当前对象的score值大
            return -1;
        } else if (this.score< s.score) { //对象o的score值大
            return 1;       
        } else {
            return 0;
        }
    }
}

我们可以看到,这时排的升序,如果要降序就只需将大于号变成小于号即可!

image.png

在 sort 方法中会自动调用compareTo 方法. compareTo 的参数是 Object , 其实传入的就是 Student类型的对象.

然后比较当前对象和参数对象的大小关系(按分数来算).

如果当前对象应排在参数对象之前, 返回小于0 的数字;

如果当前对象应排在参数对象之后, 返回大于 0 的数字;

如果当前对象和参数对象不分先后, 返回0;


注意事项: 对于 sort 方法来说, 需要传入的数组的每个对象都是 “可比较” 的, 需要具备compareTo这样的能力. 通过重写compareTo 方法的方式, 就可以定义比较规则。

为了进一步加深对接口的理解, 我们可以尝试自己实现一个sort方法来完成刚才的排序过程(使用冒泡排序)!


public static void sort(Comparable[] array) { 
    for (int bound = 0; bound < array.length; bound++) { 
        for (int cur = array.length - 1; cur > bound; cur--) { 
            if (array[cur - 1].compareTo(array[cur]) > 0) { 
                // 说明顺序不符合要求, 交换两个变量的位置 
                Comparable tmp = array[cur - 1]; 
                array[cur - 1] = array[cur]; 
                array[cur] = tmp; 
            } 
        } 
    } 
}

image.png


接口间的继承

接口可以继承一个接口, 达到复用的效果. 使用extends关键字!

interface IAmphibious extends IRunning, ISwimming {
}
class Frog implements IAmphibious {
    @Override
    public void run() {
        System.out.println("Frog run!");
    }
    @Override
    public void swim() {
        System.out.println("Frog swim!");
    }
}
public class Test_1 {
    public static void main(String[] args) {
           Frog frog = new Frog();
           frog.run();
           frog.swim();
    }
 }

image.png


通过接口继承创建一个新的接口 IAmphibious 表示 “两栖的”. 此时实现接口创建的 Frog类, 就继续要实现 run 方法,也需要实现 swim方法!


接口间的继承相当于将多个接口合并在一起!



目录
相关文章
|
12天前
|
Java
Java中的继承和多态是什么?请举例说明。
Java中,继承让子类继承父类属性和方法,如`class Child extends Parent`,子类可重写父类方法。多态允许父类引用指向子类对象,如`Animal a = new Dog()`,调用`a.makeSound()`会根据实际对象类型动态绑定相应实现,增强了代码灵活性和可扩展性。
10 0
|
16天前
|
Java
Java中的抽象类:深入了解抽象类的概念和用法
Java中的抽象类是一种不能实例化的特殊类,常作为其他类的父类模板,定义子类行为和属性。抽象类包含抽象方法(无实现)和非抽象方法。定义抽象类用`abstract`关键字,子类继承并实现抽象方法。抽象类适用于定义通用模板、复用代码和强制子类实现特定方法。优点是提供抽象模板和代码复用,缺点是限制继承灵活性和增加类复杂性。与接口相比,抽象类可包含成员变量和单继承。使用时注意设计合理的抽象类结构,谨慎使用抽象方法,并遵循命名规范。抽象类是提高代码质量的重要工具。
29 1
|
5天前
|
Java 开发者
探索 Java 的函数式接口和 Lambda 表达式
【4月更文挑战第19天】Java 中的函数式接口和 Lambda 表达式提供了简洁、灵活的编程方式。函数式接口有且仅有一个抽象方法,用于与 Lambda(一种匿名函数语法)配合,简化代码并增强可读性。Lambda 表达式的优点在于其简洁性和灵活性,常用于事件处理、过滤和排序等场景。使用时注意兼容性和变量作用域,它们能提高代码效率和可维护性。
|
6天前
|
Java
Java接口中可以定义哪些方法?
【4月更文挑战第13天】
9 0
Java接口中可以定义哪些方法?
|
8天前
|
设计模式 Java
Java接口与抽象类
Java接口与抽象类
17 0
|
12天前
|
安全 Java 编译器
接口之美,内部之妙:深入解析Java的接口与内部类
接口之美,内部之妙:深入解析Java的接口与内部类
34 0
接口之美,内部之妙:深入解析Java的接口与内部类
|
14天前
|
存储 Java
java接口和内部类
java接口和内部类
|
16天前
|
缓存 安全 Java
Java中函数式接口详解
Java 8引入函数式接口,支持函数式编程。这些接口有单一抽象方法,可与Lambda表达式结合,简化代码。常见函数式接口包括:`Function&lt;T, R&gt;`用于转换操作,`Predicate&lt;T&gt;`用于布尔判断,`Consumer&lt;T&gt;`用于消费输入,`Supplier&lt;T&gt;`用于无参生成结果。开发者也可自定义函数式接口。Lambda表达式使实现接口更简洁。注意异常处理和线程安全。函数式接口广泛应用于集合操作、并行编程和事件处理。提升代码可读性和效率,是现代Java开发的重要工具。
29 0
|
Java 编译器
java方法的重载要求与作用,重载与重写的区别
java方法的重载要求与作用,重载与重写的区别
233 0
|
前端开发 Java
店铺业务场景分析、BigDecimal是Java提供的一个不变的、任意精度的有符号十进制数对象。它提供了四个构造器,有两个是用BigInteger构造、接口怎么使用的、重载与重写的区别?分别是什么?
店铺业务场景分析 一、协同店铺、竞争店铺极海数据返回给前端数据结构不一样 导入的数据结构 很有可能和自定义采集得到的数据结构不一样
127 1
店铺业务场景分析、BigDecimal是Java提供的一个不变的、任意精度的有符号十进制数对象。它提供了四个构造器,有两个是用BigInteger构造、接口怎么使用的、重载与重写的区别?分别是什么?