Edit: To be clear I am not asking how to do enums in java. I am asking if there is something in java that is complementary to Swifts associated values in enums. This is not just simply how do I store values on enums. Take a look at the example I provided and you will see the difference.
编辑:要明确我不会问如何在java中进行枚举。我在询问java中是否存在与枚举中的Swifts相关值互补的内容。这不仅仅是如何在枚举上存储值。看看我提供的示例,您将看到不同之处。
So an iOS developer was showing me an architecture where he used swifts enum associated values. This concept seemed interesting to me I and as an android developer I was curious to see if its possible in java without being overly verbose. What is the equivalent with Java enums? Or is it not possible?
因此,iOS开发人员向我展示了一个架构,他使用了swifts枚举关联值。这个概念对我来说似乎很有趣,作为一个Android开发人员,我很想知道它是否可以在Java中使用而不会过于冗长。与Java枚举相同的是什么?或者这不可能吗?
Here is an example of what I mean by Associated Values. Its pulled form the 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).")
}
2 个解决方案
#1
8
For me with Java enums this will not be possible.
对于使用Java枚举的我来说,这是不可能的。
To be close to your posted snippet you would be verbose, as you already assume.
如您已经假设的那样,要接近您发布的代码片段,您将会很详细。
enum
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 implementation UPCA
具体实施UPCA
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 QRCode
具体实现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
#2
2
I also struggled with this question, and came up with the following solution. Notably, I don't even use enums, since Java's enums are not well-suited to the task. The important part is that you need switch
-like behaviour for the cases, with the associated values available in each case.
我也在努力解决这个问题,并想出了以下解决方案。值得注意的是,我甚至不使用枚举,因为Java的枚举不适合这项任务。重要的是,您需要案例的类似开关的行为,并在每种情况下都提供相关的值。
enum-like 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
pros
- Much less implementation code than enum-based solutions
- Even less code at usage site than enum-based solutions
实现代码比基于枚举的解决方案少得多
使用网站上的代码甚至比基于枚举的解决方案更少
cons
- Lots of awkward nesting in
Barcode
implementation. Just Java being ugly. - You can't throw exceptions from the switch case actions.
- Angle bracket blindness in
UPCA
implementation, due to having many arguments. To prevent this leaking into the API, you could declare apublic interface UPCAConsumer extends IntFunction<IntFunction<IntFunction<IntConsumer>>> {}
, and useUPCAConsumer
for thecaseUPCA(action)
argument type.
Barcode实现中有很多笨拙的嵌套。只是Java丑陋。
您不能从switch case操作中抛出异常。
UPCA实施中的角括号盲,由于有许多参数。为了防止泄漏到API中,您可以声明一个公共接口UPCAConsumer扩展IntFunction
#1
8
For me with Java enums this will not be possible.
对于使用Java枚举的我来说,这是不可能的。
To be close to your posted snippet you would be verbose, as you already assume.
如您已经假设的那样,要接近您发布的代码片段,您将会很详细。
enum
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 implementation UPCA
具体实施UPCA
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 QRCode
具体实现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
#2
2
I also struggled with this question, and came up with the following solution. Notably, I don't even use enums, since Java's enums are not well-suited to the task. The important part is that you need switch
-like behaviour for the cases, with the associated values available in each case.
我也在努力解决这个问题,并想出了以下解决方案。值得注意的是,我甚至不使用枚举,因为Java的枚举不适合这项任务。重要的是,您需要案例的类似开关的行为,并在每种情况下都提供相关的值。
enum-like 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
pros
- Much less implementation code than enum-based solutions
- Even less code at usage site than enum-based solutions
实现代码比基于枚举的解决方案少得多
使用网站上的代码甚至比基于枚举的解决方案更少
cons
- Lots of awkward nesting in
Barcode
implementation. Just Java being ugly. - You can't throw exceptions from the switch case actions.
- Angle bracket blindness in
UPCA
implementation, due to having many arguments. To prevent this leaking into the API, you could declare apublic interface UPCAConsumer extends IntFunction<IntFunction<IntFunction<IntConsumer>>> {}
, and useUPCAConsumer
for thecaseUPCA(action)
argument type.
Barcode实现中有很多笨拙的嵌套。只是Java丑陋。
您不能从switch case操作中抛出异常。
UPCA实施中的角括号盲,由于有许多参数。为了防止泄漏到API中,您可以声明一个公共接口UPCAConsumer扩展IntFunction