
/**
 * 实验名称：继承、抽象类、多态、接口的使用
 * 实验内容：多格式音乐播放器系统
 */

// 一、定义抽象类 MusicFile
abstract class MusicFile {
    private String fileName;
    private double fileSize;

    public MusicFile(String fileName, double fileSize) {
        this.fileName = fileName;
        this.fileSize = fileSize;
    }

    public String getFileName() {
        return fileName;
    }

    public void setFileName(String fileName) {
        this.fileName = fileName;
    }

    public double getFileSize() {
        return fileSize;
    }

    public void setFileSize(double fileSize) {
        this.fileSize = fileSize;
    }

    // 获取文件类型
    public abstract String getFileType();

    // 解码音乐
    public abstract void decode();

    // 播放音乐
    public abstract void play();
}


// 二、定义播放接口 Playable
interface Playable {
    void play();
    void stop();
}


// 三、MP3 音乐文件类
class MP3File extends MusicFile implements Playable {

    public MP3File(String fileName, double fileSize) {
        super(fileName, fileSize);
    }

    @Override
    public String getFileType() {
        return "MP3";
    }

    @Override
    public void decode() {
        System.out.println("正在解码MP3有损压缩音频...");
    }

    @Override
    public void play() {
        System.out.println("正在播放MP3音乐：" + getFileName());
    }

    @Override
    public void stop() {
        System.out.println("MP3音乐已停止播放");
    }
}


// 四、WAV 音乐文件类
class WAVFile extends MusicFile implements Playable {

    public WAVFile(String fileName, double fileSize) {
        super(fileName, fileSize);
    }

    @Override
    public String getFileType() {
        return "WAV";
    }

    @Override
    public void decode() {
        System.out.println("正在读取WAV的PCM音频数据...");
    }

    @Override
    public void play() {
        System.out.println("正在播放WAV音乐：" + getFileName());
    }

    @Override
    public void stop() {
        System.out.println("WAV音乐已停止播放");
    }
}


// 五、FLAC 音乐文件类
class FLACFile extends MusicFile implements Playable {

    public FLACFile(String fileName, double fileSize) {
        super(fileName, fileSize);
    }

    @Override
    public String getFileType() {
        return "FLAC";
    }

    @Override
    public void decode() {
        System.out.println("正在解码FLAC无损压缩音频...");
    }

    @Override
    public void play() {
        System.out.println("正在播放FLAC音乐：" + getFileName());
    }

    @Override
    public void stop() {
        System.out.println("FLAC音乐已停止播放");
    }
}


// 六、音乐播放器类
class MusicPlayer {

    private String playerName;

    public MusicPlayer(String playerName) {
        this.playerName = playerName;
    }

    public String getPlayerName() {
        return playerName;
    }

    public void setPlayerName(String playerName) {
        this.playerName = playerName;
    }

    // 使用抽象类作为参数，体现多态
    public void playMusic(MusicFile musicFile) {
        System.out.println("\n========== 开始播放 ==========");
        System.out.println("播放器：" + playerName);
        System.out.println("文件名称：" + musicFile.getFileName());
        System.out.println("文件大小：" + musicFile.getFileSize() + " MB");
        System.out.println("文件格式：" + musicFile.getFileType());

        // 根据实际对象类型调用对应的方法
        musicFile.decode();
        musicFile.play();
    }

    // 使用接口作为参数
    public void stopMusic(Playable playable) {
        playable.stop();
        System.out.println("========== 播放结束 ==========");
    }
}


// 七、测试类（程序入口）
public class MusicPlayerTest {

    public static void main(String[] args) {

        // 创建播放器对象
        MusicPlayer player = new MusicPlayer("我的音乐播放器");

        // 父类引用指向子类对象，体现多态
        MusicFile mp3 = new MP3File("晴天.mp3", 4.8);
        MusicFile wav = new WAVFile("钢琴曲.wav", 38.2);
        MusicFile flac = new FLACFile("夜曲.flac", 25.6);

        // 使用父类数组统一管理音乐文件
        MusicFile[] musicFiles = {mp3, wav, flac};

        // 循环播放不同格式的音乐
        for (MusicFile music : musicFiles) {

            // 多态调用解码、播放方法
            player.playMusic(music);

            // 转换为接口类型，调用停止方法
            Playable playable = (Playable) music;
            player.stopMusic(playable);
        }

        // 测试接口多态
        System.out.println("\n========== 接口多态测试 ==========");

        Playable p1 = new MP3File("测试1.mp3", 3.5);
        Playable p2 = new WAVFile("测试2.wav", 15.0);
        Playable p3 = new FLACFile("测试3.flac", 20.0);

        p1.stop();
        p2.stop();
        p3.stop();

        // 测试 getter 和 setter
        System.out.println("\n========== 封装测试 ==========");

        mp3.setFileName("修改后的歌曲.mp3");
        mp3.setFileSize(5.2);

        System.out.println("修改后文件名：" + mp3.getFileName());
        System.out.println("修改后文件大小：" + mp3.getFileSize() + " MB");

        player.setPlayerName("新版音乐播放器");
        System.out.println("修改后播放器名称：" + player.getPlayerName());

        System.out.println("\n所有测试完成！");
    }
}
