How to use data classes in java, without getter Methods?

Viewed 113

A program needs an object with both static and non-static data. All data-classes should implement/extend the same class/interface so to be able to do:

Color color1 = new Navy();

To simplify it, lets take color storing classes an a Example. These color classes store a color and can calculate a custom mixture from their own and a passed color.

interface Color {
    public static final int hex;
    public int mix;
}
class Navy implements Color {
    public static final int hex = 0x000080;
    public int mix;
    public Navy(int otherColor) {
        mix = otherColor -128 +hex;
    } 
}
class Maroon implements Color {
    public static final int hex = 0x800000;
    public int mix;
    public Maroon(int otherColor) {
        mix = otherColor -56 +hex;
    } 
}

class DarkMagenta implements Color {
    public static final int hex = 0x8B008B;
    public int mix;
    public DarkMagenta(int otherColor) {
        mix = otherColor +180 +hex;
    } 
}

I know that all variables in an interface are static final and when using abstract classes, it is possible to declare an abstract method that has to be implemented but not an abstract variable.

What is a commonly good solution that doesn't require getters for everything and saves writing code?

EDIT:

Both the interface way:

interface Color {
    public static final int hex=0;
    public int mix=0;
}
class Navy implements Color {
    public static final int hex = 0x000080;
    public int mix;
    public Navy(int otherColor) {
        mix = otherColor -128 +hex;
    } 
}
class Maroon implements Color {
    public static final int hex = 0x800000;
    public int mix;
    public Maroon(int otherColor) {
        mix = otherColor -56 +hex;
    } 
}

class DarkMagenta implements Color {
    public static final int hex = 0x8B008B;
    public int mix;
    public DarkMagenta(int otherColor) {
        mix = otherColor +180 +hex;
    } 
}

and the abstact class way:

abstract class Color {
    public static final int hex=0;
    public int mix;
}
class Navy extends Color {
    public static final int hex = 0x000080;
    public int mix;
    public Navy(int otherColor) {
        mix = otherColor -128 +hex;
    } 
}
class Maroon extends Color {
    public static final int hex = 0x800000;
    public int mix;
    public Maroon(int otherColor) {
        mix = otherColor -56 +hex;
    } 
}

class DarkMagenta extends Color {
    public static final int hex = 0x8B008B;
    public int mix;
    public DarkMagenta(int otherColor) {
        mix = otherColor +180 +hex;
    } 
}

do not do what i want:

    //this works but
    Navy color1 = new Navy(9);
    System.out.println(color1.hex);// 128
    

    // not this
    Color color2 = new Navy(9);
    System.out.println(color2.hex);// 0

All colors should be a child member of Color.

4 Answers

There is no such notion as 'abstract variable'. It is either a variable or a constant. Constants in java are declared using final modifier. And if it is a static constant (static means belonging to a class and static elements cant be inherited) it must be initialized within declaration or inside the static initializer block.

In interfaces, you can declare only public static final fields (by the way all these modifiers can be omitted), and as soon as static blocks are not allowed in interfaces you have to provide values within declarations.

Like that, or else it'll not compile:

interface Color {
    public static final int hex = 0x000080;
    public int mix = 127;
}

This is a place where using enums makes sense. Enum values are subclasses, no getters are needed, and there could not be less boilerplate, so this seems like what you asked for.

enum Color {
    NAVY(0x000080, -128),
    MAROON(0x800000, 56),
    DARK_MAGENTA(0x8B008B, 180);

    final int hex;
    final int mixOffset;

    Color(int hex, int mixOffset) {
        this.hex = hex;
        this.mixOffset = mixOffset;
    }

    int mix(Color other) {
        return other.hex + mixOffset + hex;
    }
}

The Planets example from the Java tutorial shows something very similar: https://docs.oracle.com/javase/tutorial/java/javaOO/enum.html

Abstract classes seem to provide the functionality you want. Almost. There is no such thing as "abstract variable". Although you can still achieve this by initialising the constants via constructor.

abstract class Color {
    public final int hex;
    public int mix;
    Color(int hex) {
        this.hex = hex;
    }
}

class Navy extends Color {
    public Navy(int otherColor) {
        super(0x000080); // constant hex value
        this.mix = otherColor - 128 + hex;
    }
}

In the code above the hex field is not static, but it is constant. So these code snippets will work just fine:

// this works
Navy color1 = new Navy(9);
System.out.println(color1.hex); // 128

// this works
Color color2 = new Navy(9);
System.out.println(color2.hex);

// this works as well
Color color3 = new Navy(9);
System.out.println(color3.mix);

If you are interested to "save writing code" you could have a look into https://projectlombok.org/

It is discussed controversial and from my experience you can expect to spend the time that you save on writing code later when you come back to formerly written code when you want to understand what's actually going on due to the "magic behind the curtains".

But project lombok has been here for quite a while, so clearly there are many developers finding it really useful.

Short explanation of what it (also) does: it generates getters and setters for you without actually putting them into source code. Driven by annotations.

Related