1. 概述

在这个教程中,我们将探讨面向对象编程中的关键概念之一——继承。在Java中,用于继承的主要关键字是extendsimplements

2. extendsimplements

让我们来讨论这两个关键字之间的差异。

我们使用extends关键字从一个类继承属性和方法。 被当作父类的那个类称为基类,而从这个基类继承的类被称为派生类或子类。主要地,extends关键字用于将父类的功能扩展到派生类中。此外,一个基类可以有多个派生类,但派生类只能有一个基类,因为Java不支持多重继承。

另一方面,我们使用implements关键字实现接口。 接口只包含抽象方法。一个类将实现这个接口,并根据需要的功能定义这些抽象方法。extends不同,任何类都可以实现多个接口。

尽管两个关键字都符合继承的概念,但implements关键字主要与抽象相关,用于定义契约,而extends用于扩展类已有的功能。

3. 实现

现在,让我们深入探讨extendsimplements和多重继承的实现。

3.1. extends

首先,我们创建一个名为Media的类,它有idtitleartist属性。这个类将作为基础类。VideoMediaAudioMedia将扩展这个类的功能:

public class Media {

    private int id;
    private String title;
    private String artist;
    // standard getters and setters
}

现在,我们创建一个名为VideoMedia的类,它extendsMedia,继承其属性。此外,它还有自己的属性,如resolutionaspectRatio

public class VideoMedia extends Media {

    private String resolution;
    private String aspectRatio;
    // standard getters and setters
}

同样,AudioMedia类也extendsMedia,并会添加自己的额外属性,如bitratefrequency

public class AudioMedia extends Media {

    private int bitrate;
    private String frequency;
    // standard getters and setters

    @Override
    public void printTitle() {
        System.out.println("AudioMedia Title");
    }
}

让我们创建基类和派生类的对象,看看继承的属性:

Media media = new Media();
media.setId(001);
media.setTitle("Media1");
media.setArtist("Artist001");

AudioMedia audioMedia = new AudioMedia();
audioMedia.setId(101);
audioMedia.setTitle("Audio1");
audioMedia.setArtist("Artist101");
audioMedia.setBitrate(3500);
audioMedia.setFrequency("256kbps");

VideoMedia videoMedia = new VideoMedia();
videoMedia.setId(201);
videoMedia.setTitle("Video1");
videoMedia.setArtist("Artist201");
videoMedia.setResolution("1024x768");
videoMedia.setAspectRatio("16:9");

System.out.println(media);
System.out.println(audioMedia);
System.out.println(videoMedia);

这三个类都打印关联的属性:

Media{id=1, title='Media1', artist='Artist001'}
AudioMedia{id=101, title='Audio1', artist='Artist101', bitrate=3500, frequency='256kbps'} 
VideoMedia{id=201, title='Video1', artist='Artist201'resolution='1024x768', aspectRatio='16:9'} 

3.2. implements

为了理解抽象和接口,我们将创建一个名为MediaPlayer的接口,它有两个方法playpause。如前所述,接口中的所有方法都是抽象的。换句话说,接口仅包含方法声明。

在Java中,接口不需要明确声明方法为abstractpublic 实现MediaPlayer接口的类将定义这些方法:

public interface MediaPlayer {

    void play();

    void pause();
}

AudioMediaPlayerimplements``MediaPlayer,并将为音频媒体定义playpause方法:

public class AudioMediaPlayer implements MediaPlayer {

    @Override
    public void play() {
        System.out.println("AudioMediaPlayer is Playing");
    }

    @Override
    public void pause() {
        System.out.println("AudioMediaPlayer is Paused");
    }
}

类似地,VideoMediaPlayer implements MediaPlayer并提供视频媒体的playpause方法定义:

public class VideoMediaPlayer implements MediaPlayer {

    @Override
    public void play() {
        System.out.println("VideoMediaPlayer is Playing");
    }

    @Override
    public void pause() {
        System.out.println("VideoMediaPlayer is Paused");
    }
}

然后,我们创建一个AudioMediaPlayerVideoMediaPlayer的实例,并分别调用它们的playpause方法:

AudioMediaPlayer audioMediaPlayer = new AudioMediaPlayer();
audioMediaPlayer.play();
audioMediaPlayer.pause();

VideoMediaPlayer videoMediaPlayer = new VideoMediaPlayer();
videoMediaPlayer.play();
videoMediaPlayer.pause();

AudioMediaPlayerVideoMediaPlayer调用自己的playpause实现:

AudioMediaPlayer is Playing
AudioMediaPlayer is Paused

VideoMediaPlayer is Playing
VideoMediaPlayer is Paused

3.3. 多重继承

由于存在歧义问题,Java不直接支持多重继承。 当一个类从两个以上的父类继承时,如果两个父类都有同名的方法或属性,就会出现歧义问题。因此,子类无法解决方法或属性继承的冲突。然而,类可以继承自多个接口。 我们创建一个名为AdvancedPlayerOptions的接口:

public interface AdvancedPlayerOptions {

    void seek();

    void fastForward();
}

MultiMediaPlayerimplements``MediaPlayerAdvancedPlayerOptions,并定义了两个接口中声明的方法:

public class MultiMediaPlayer implements MediaPlayer, AdvancedPlayerOptions {

    @Override
    public void play() {
        System.out.println("MultiMediaPlayer is Playing");
    }

    @Override
    public void pause() {
        System.out.println("MultiMediaPlayer is Paused");
    }

    @Override
    public void seek() {
        System.out.println("MultiMediaPlayer is being seeked");
    }

    @Override
    public void fastForward() {
        System.out.println("MultiMediaPlayer is being fast forwarded");
    }
}

现在,我们创建MultiMediaPlayer类的实例,并调用所有实现的方法:

MultiMediaPlayer multiMediaPlayer = new MultiMediaPlayer();
multiMediaPlayer.play();
multiMediaPlayer.pause();
multiMediaPlayer.seek();
multiMediaPlayer.fastForward();

正如预期的那样,MultiMediaPlayer调用自己的playpause实现:

MultiMediaPlayer is Playing
MultiMediaPlayer is Paused 
MultiMediaPlayer is being seeked 
MultiMediaPlayer is being fast forwarded

4. 结论

在这篇教程中,我们详细讨论了extendsimplements之间的主要区别。我们通过创建类和接口展示了extendsimplements的概念。同时,我们也讨论了多重继承以及如何通过接口实现它。

这个实现可以在GitHub上找到。