How can I create a Java enum with associated values ​​like Swift enum?

Edit: To be clear, I am not asking how to do enums in java. I am asking if there is something in java that complements the associated Swifts values ​​in enums. It's not just how to store values ​​in enums. Take a look at the example I gave and you will see the difference.

So, an iOS developer showed me an architecture where he used transition related enums. I found the concept interesting to me, and as an android developer I'm curious to know if this is possible in Java without being too verbose. What is the equivalent of Java enums? Or is it impossible?

Here is an example of what I mean by associated values. It was pulled from apple docs.

enum Barcode {
    case UPCA(Int, Int, Int, Int)
    case QRCode(String)
}

// Instantiated
var productBarcode = Barcode.UPCA(8, 85909, 51226, 3)
// or
productBarcode = .QRCode("ABCDEFGHIJKLMNOP")


switch productBarcode {
case .UPCA(let numberSystem, let manufacturer, let product, let check):
    println("UPC-A: \(numberSystem), \(manufacturer), \(product), \(check).")
case .QRCode(let productCode):
    println("QR code: \(productCode).")
}

      

+3


source to share


2 answers


For me with Java enums, this won't be possible.

To be closer to your posted snippet you would be as detailed as you already assumed.

enumeration

enum BarcodeType {
    UPCA,
    QRCode,
    UNDEFINED;
}

      

factory class

abstract class Barcode {

    abstract public BarcodeType getType();

    public static final Barcode newUPCA(int numberSystem, int manufacturer, int product, int check) {
        return new BarcodeUPCA(numberSystem, manufacturer, product, check);
    }

    public static final Barcode newQRCode(String productCode) {
        return new BarcodeQRCode(productCode);
    }
}

      

concrete UPCA implementation



class BarcodeUPCA extends Barcode {
    private final int numberSystem;
    private final int manufacturer;
    private final int product;
    private final int check;

    public BarcodeUPCA(int numberSystem, int manufacturer, int product, int check) {
        this.numberSystem = numberSystem;
        this.manufacturer = manufacturer;
        this.product = product;
        this.check = check;
    }

    public int getNumberSystem() {
        return numberSystem;
    }

    public int getManufacturer() {
        return manufacturer;
    }

    public int getProduct() {
        return product;
    }

    public int getCheck() {
        return check;
    }

    @Override
    public BarcodeType getType() {
        return BarcodeType.UPCA;
    }
}

      

concrete implementation of QRCode

class BarcodeQRCode extends Barcode {

    private final String productCode;

    public BarcodeQRCode(String productCode) {
        this.productCode = productCode;
    }

    public String getProductCode() {
        return productCode;
    }

    @Override
    public BarcodeType getType() {
        return BarcodeType.QRCode;
    }
}

      

demo application

public class BarcodeMain {

    public static void main(String[] args) throws Exception {
        List<Barcode> barcodes = new ArrayList<>();
        barcodes.add(Barcode.newUPCA(8, 85909, 51226, 3));
        barcodes.add(Barcode.newQRCode("foobar"));

        for (Barcode barcode : barcodes) {
            switch (barcode.getType()) {
                case UPCA: {
                    BarcodeUPCA b = (BarcodeUPCA) barcode;
                    System.out.printf("UPC-A: %d, %d, %d, %d%n",
                            b.getNumberSystem(),
                            b.getManufacturer(),
                            b.getProduct(),
                            b.getCheck()
                    );
                    break;
                }
                case QRCode: {
                    BarcodeQRCode b = (BarcodeQRCode) barcode;
                    System.out.printf("QR code: %s%n", b.getProductCode());
                    break;
                }
                default:
                    System.err.println("unhandled type: " + barcode.getType());
            }
        }
}

      

Output

UPC-A: 8, 85909, 51226, 3
QR code: foobar

      

+6


source


I also wrestled with this question and came up with the following solution. Remarkably, I don't even use enums as Java enums are not suitable for the task. The important part is that for the cases, you want a behavior- switch

like behavior , with the appropriate values ​​available in each case.

enumerated type

public abstract class Barcode
{
    private Barcode() {}

    void caseUPCA(IntFunction<IntFunction<IntFunction<IntConsumer>>> action) {}
    void caseQRCode(Consumer<String> action) {}

    static Barcode UPCA(int numberSystem, int manufacturer, int product, int check)
    {
        return new Barcode()
        {
            @Override public void caseUPCA(IntFunction<IntFunction<IntFunction<IntConsumer>>> action)
            {
                action.apply(numberSystem).apply(manufacturer).apply(product).accept(check);
            }
        };
    }

    static Barcode QRCode(String text)
    {
        return new Barcode()
        {
            @Override public void caseQRCode(Consumer<String> action)
            {
                action.accept(text);
            }
        };
    }
}

      

demo application

public class BarcodeMain
{
    public static void main(String[] args) throws Exception
    {
        List<Barcode> barcodes = new ArrayList<>();
        barcodes.add(Barcode.UPCA(8, 85909, 51226, 3));
        barcodes.add(Barcode.QRCode("foobar"));

        for(Barcode barcode: barcodes)
        {
            barcode.caseUPCA(numberSystem -> manufacturer -> product -> check ->
                System.out.printf("UPC-A: %d, %d, %d, %d%n", numberSystem, manufacturer, product, check));
            barcode.caseQRCode(productCode ->
                System.out.printf("QR code: %s%n", productCode));
        }
    }
}

      

Output



UPC-A: 8, 85909, 51226, 3
QR code: foobar

      

the pros

  • Significantly less implementation code than enum based solutions
  • Even less code on site use than enum based solutions

against

  • A lot of awkward nests in the implementation Barcode

    . It's just that Java is ugly.
  • You cannot throw exceptions from the actions of a switch statement.
  • Corollary of angle brackets in implementation UPCA

    due to multiple arguments. To prevent leakage to the API, you can declare public interface UPCAConsumer extends IntFunction<IntFunction<IntFunction<IntConsumer>>> {}

    and use UPCAConsumer

    for the argument type caseUPCA(action)

    .
+2


source







All Articles