我在Eclipse中使用Java,并且阅读了thread

我真的很喜欢home's answer,因为我以前从没想过。子类实际上应该没有访问成员的整个想法。但是,如果有人想放手一搏,我有一个有趣的例子。

假设我有一个接口Buildable和一个枚举CatanPiece

public interface Buildable
{
    HashMap<Resource, Integer> getCost();
    Buildable build( final PlayerHand payment );
}

public enum CatanPiece implements Buildable
{
    ROAD
    {
        @Override
        public HashMap<Resource, Integer> getCost()
        {
            if ( cost.isEmpty() )
            {
                cost.put( BRICK, 1 );
                cost.put( LUMBER, 1 );
            }
            return cost;
        }
    },

    SETTLEMENT
    {
        @Override
        public HashMap<Resource, Integer> getCost()
        {
            if ( cost.isEmpty() )
            {
                cost.put( BRICK, 1 );
                cost.put( LUMBER, 1 );
                cost.put( SHEEP, 1 );
                cost.put( WHEAT, 1 );
            }
            return cost;
        }
    },

    CITY
    {
        @Override
        public HashMap<Resource, Integer> getCost()
        {
            if ( cost.isEmpty() )
            {
                cost.put( WHEAT, 2 );
                cost.put( ORE, 3 );
            }
            return cost;
        }
    };

    protected final HashMap<Resource, Integer> cost;

    private CatanPiece()
    {
        cost = getCost();
    }

    @Override
    public abstract HashMap<Resource, Integer> getCost();

    @Override
    public Buildable build( final PlayerHand payment )
    {
        return ( payment.remove( cost ) ? null : this );
    }
}


所以Checkstyle给了我有关我正在使用的受保护的HashMap的信息,但是对于那些了解此问题的人来说,您可以看到我没有有人滥用该变量的问题。并且我实际上将其设为私有并使用受保护的get方法,但是该方法在每个实例上的返回都是不同的。

可能的答案:忽略checkstyle警告,或者包括抽象的init()方法来初始化HashMap,然后简单地为枚举的所有成员简单地实现getCost()方法。

你怎么看?

最佳答案

Checkstyle对枚举的理解有时不完整。我猜想VisibilityModifier检查的作者没有想到Enums。枚举是一个极端的情况,需要支票的某些其他属性。

但是,偶然地,对于您而言,警告仍然是正确的。我认为,在任何情况下都不应在枚举中使用protected字段。如果在Enum常量中需要实例特定的状态,请通过构造函数或通过静态初始化对其进行初始化。

请尝试以下方法。这应该为您带来一些好处:


Checkstyle警告消失了,因为Map现在是private
现在,CatanPiece枚举常量实际上是常量,因为成本映射图是不可变的。
惰性初始化没有开销。 CatanPiece枚举常量的用户可以确保成本图正确初始化。


唯一的缺点是,每当扩展枚举时(例如,使用SHIP),开发人员都不得忘记更新buildCostMap()。这样的错误会很快出现。

public enum CatanPiece implements Buildable
{
    ROAD, SETTLEMENT, CITY;

    private static final Map<CatanPiece, Map<Resource, Integer>> allCosts =
            buildCostMap();

    private static Map<CatanPiece, Map<Resource, Integer>> buildCostMap()
    {
        Map<CatanPiece, Map<Resource, Integer>> result =
            new HashMap<CatanPiece, Map<Resource, Integer>>();

        Map<Resource, Integer> cost = new EnumMap<Resource, Integer>(Resource.class);
        cost.put(Resource.WHEAT, 2);
        cost.put(Resource.ORE, 3);
        result.put(CITY, Collections.unmodifiableMap(cost));

        cost = new EnumMap<Resource, Integer>(Resource.class);
        cost.put(Resource.BRICK, 1);
        cost.put(Resource.LUMBER, 1);
        cost.put(Resource.SHEEP, 1);
        cost.put(Resource.WHEAT, 1);
        result.put(SETTLEMENT, Collections.unmodifiableMap(cost));

        cost = new EnumMap<Resource, Integer>(Resource.class);
        cost.put(Resource.BRICK, 1);
        cost.put(Resource.LUMBER, 1);
        result.put(ROAD, Collections.unmodifiableMap(cost));

        return Collections.unmodifiableMap(result);
    }

    @Override
    public Map<Resource, Integer> getCost() {
        return allCosts.get(this);
    }

    @Override
    public Buildable build(final PlayerHand payment) {
        return payment.remove(cost) ? null : this;
    }
}

关于java - Checkstyle默认情况下不允许使用 protected 变量,但是枚举又如何呢?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/23173680/

10-16 23:30