Protected Variables aren't allowed by default in Checkstyle, but what about in an enum?

aaiezza

I'm using Java in eclipse, and I read a thread

I really liked home's answer, because I never really thought about it before. The whole idea that subclasses should really not have access to members that is. However, I have an interesting edge case if someone wants to give it a go.

Suppose I have an interface Buildable and an Enum 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 );
    }
}

So Checkstyle is giving me crap about the protected HashMap I'm using, but for those looking at this question that understand it, you can see I don't have the problem of someone misusing that variable. AND I would in fact make it private and use a protected get method, however the return on that method is different per instance.

Potential answers: Ignore the checkstyle warning, or perhaps include an abstract init() method to initialize the HashMap then simply implement the getCost() method generically for all memebers of the enum.

What do you think?

barfuin

Checkstyle's understanding of Enums is sometimes incomplete. I would guess that the author of the VisibilityModifier check did not think of Enums. Enums are a corner case that would require some additional properties of the check.

However, accidentally, in your case, the warning is still correct. I believe that there is no situation where you should use protected fields in an Enum. If you need instance specific state in your Enum constants, initialize it via the constructor or via static initialization.

Try the following approach. This should gain you several benefits:

  • The Checkstyle warning goes away because the Map is now private.
  • The CatanPiece enum constants are now really constants because the cost map is immutable.
  • No overhead for lazy initialization. Users of the CatanPiece enum constants can be sure that the costs map is initialized properly.

The only downside is that whenever the Enum is extended (e.g. with SHIP), the developer must not forget to update buildCostMap(). Such a bug would show up very quickly though.

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;
    }
}

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

Why aren't SAS Macro Variables Local-Scope by Default?

From Dev

Swift: why aren't all variables lazy by default?

From Dev

dart variables aren't equal to what they're set to be in the constructor of an object

From Dev

Why aren't abstract constructors allowed?

From Dev

SassError: Parentheses aren't allowed in plain CSS

From Dev

What are the access modifiers allowed for protected methods

From Dev

What are the allowed types for an enum (class)?

From Dev

Why aren't multimedia codecs included by default?

From Dev

AWS ECS Environment variables aren't set

From Dev

Class variables values aren't being updated

From Dev

Java - Why array constants aren't allowed as Annotation attribute value?

From Dev

Haskell: Why aren't infix type constructors allowed?

From Dev

Path construction or drawing operators aren't allowed inside a text object

From Dev

what aren't I getting here?

From Dev

What are the environment variables by default?

From Dev

Java checkstyle error "Declaring variables, return values or parameters of type 'Integer' is not allowed."

From Dev

Foundation Tooltips aren’t working; instead show default browser tooltip

From Dev

Why aren't C++ types const by default?

From Java

Are default arguments of object type constructed every time they aren't specified?

From Dev

Why aren't include guards in c++ the default?

From Dev

Why aren't Enumerators in Ruby (2.0 +) lazy by default?

From Dev

Why aren't DIVs with given widths including paddings and borders by default?

From Dev

Why aren't third-party cookies disabled by default?

From Dev

Foundation Tooltips aren’t working; instead show default browser tooltip

From Dev

Files created by 'make' aren't getting executable permissions by default

From Dev

AngularJS ng-repeat radio buttons aren't checked by default

From Dev

How to know what are in a file and what aren't in another?

From Dev

Where to set variables so that they aren't null on postback?

From Dev

Why aren't there existentially quantified type variables in GHC Haskell

Related Related

  1. 1

    Why aren't SAS Macro Variables Local-Scope by Default?

  2. 2

    Swift: why aren't all variables lazy by default?

  3. 3

    dart variables aren't equal to what they're set to be in the constructor of an object

  4. 4

    Why aren't abstract constructors allowed?

  5. 5

    SassError: Parentheses aren't allowed in plain CSS

  6. 6

    What are the access modifiers allowed for protected methods

  7. 7

    What are the allowed types for an enum (class)?

  8. 8

    Why aren't multimedia codecs included by default?

  9. 9

    AWS ECS Environment variables aren't set

  10. 10

    Class variables values aren't being updated

  11. 11

    Java - Why array constants aren't allowed as Annotation attribute value?

  12. 12

    Haskell: Why aren't infix type constructors allowed?

  13. 13

    Path construction or drawing operators aren't allowed inside a text object

  14. 14

    what aren't I getting here?

  15. 15

    What are the environment variables by default?

  16. 16

    Java checkstyle error "Declaring variables, return values or parameters of type 'Integer' is not allowed."

  17. 17

    Foundation Tooltips aren’t working; instead show default browser tooltip

  18. 18

    Why aren't C++ types const by default?

  19. 19

    Are default arguments of object type constructed every time they aren't specified?

  20. 20

    Why aren't include guards in c++ the default?

  21. 21

    Why aren't Enumerators in Ruby (2.0 +) lazy by default?

  22. 22

    Why aren't DIVs with given widths including paddings and borders by default?

  23. 23

    Why aren't third-party cookies disabled by default?

  24. 24

    Foundation Tooltips aren’t working; instead show default browser tooltip

  25. 25

    Files created by 'make' aren't getting executable permissions by default

  26. 26

    AngularJS ng-repeat radio buttons aren't checked by default

  27. 27

    How to know what are in a file and what aren't in another?

  28. 28

    Where to set variables so that they aren't null on postback?

  29. 29

    Why aren't there existentially quantified type variables in GHC Haskell

HotTag

Archive