You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用组合而非继承时,数组应存储何种类型?

组合模式下如何存储不同类的实例到同一数组中

在继承场景中,我们可以通过父类数组直接存储子类实例,但在组合模式下,Player和Monster只是持有Entity字段,并无继承关系,无法直接存入Entity[]数组。要解决这个问题,有以下几种可行方案:

方案1:定义共同接口(推荐)

创建一个包含获取Entity方法的接口,让Player和Monster都实现该接口,数组使用接口类型,既保证类型安全,又符合面向接口编程的原则。

// 定义共同接口
interface HasEntity {
    Entity getEntity();
}

class Entity {
    public int id;

    public Entity() {
        this.id = 0;
    }
}

class Player implements HasEntity {
    Entity entity;

    public Player() {
        this.entity = new Entity();
        this.entity.id = 1;
    }

    @Override
    public Entity getEntity() {
        return entity;
    }
}

class Monster implements HasEntity {
    Entity entity;

    public Monster() {        
        this.entity = new Entity();
        this.entity.id = 2;
    }

    @Override
    public Entity getEntity() {
        return entity;
    }
}

public class Main {
    public static void main(String[] args) {
        Player player = new Player();
        Monster monster = new Monster();
        
        HasEntity[] entities = new HasEntity[2];
        entities[0] = player;
        entities[1] = monster;

        // 通过接口方法统一获取Entity
        System.out.println(entities[0].getEntity().id); // 输出1
        System.out.println(entities[1].getEntity().id); // 输出2
    }
}

方案2:使用Object数组(不推荐)

Java中所有类都继承自Object,因此可以用Object[]存储任意对象,但这种方式会丢失类型信息,需要强制转换才能访问内部字段,容易引发ClassCastException,类型安全性差,仅适合临时场景。

class Entity {
    public int id;

    public Entity() {
        this.id = 0;
    }
}

class Player {
    Entity entity;

    public Player() {
        this.entity = new Entity();
        this.entity.id = 1;
    }
}

class Monster {
    Entity entity;

    public Monster() {        
        this.entity = new Entity();
        this.entity.id = 2;
    }
}

public class Main {
    public static void main(String[] args) {
        Player player = new Player();
        Monster monster = new Monster();
        
        Object[] entities = new Object[2];
        entities[0] = player;
        entities[1] = monster;

        // 必须强制转换才能访问内部字段
        System.out.println(((Player) entities[0]).entity.id); // 输出1
        System.out.println(((Monster) entities[1]).entity.id); // 输出2
    }
}

方案3:定义抽象父类

创建一个抽象类作为Player和Monster的父类,统一类型的同时,可以在抽象类中封装通用逻辑,适合需要共享部分实现的场景。

abstract class EntityHolder {
    protected Entity entity;

    // 提供统一的获取Entity方法
    public Entity getEntity() {
        return entity;
    }
}

class Entity {
    public int id;

    public Entity() {
        this.id = 0;
    }
}

class Player extends EntityHolder {
    public Player() {
        this.entity = new Entity();
        this.entity.id = 1;
    }
}

class Monster extends EntityHolder {
    public Monster() {        
        this.entity = new Entity();
        this.entity.id = 2;
    }
}

public class Main {
    public static void main(String[] args) {
        Player player = new Player();
        Monster monster = new Monster();
        
        EntityHolder[] entities = new EntityHolder[2];
        entities[0] = player;
        entities[1] = monster;

        System.out.println(entities[0].getEntity().id); // 输出1
        System.out.println(entities[1].getEntity().id); // 输出2
    }
}

总结

  • 优先选择方案1(接口),灵活性高、类型安全,符合面向对象设计原则。
  • 方案3(抽象类)适合需要共享通用逻辑的场景。
  • 方案2(Object数组)仅作为临时妥协方案,不推荐在生产代码中使用。

内容的提问来源于stack exchange,提问作者cardiaque66

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 14:14:57