如何在不编写“if 语句”的情况下初始化输入字段?
我有一个枚举,就像
public enum Field {
A, B, C, D, E ....;
private Field(){
}
}
我有一个 class Panel
一样,它需要 Field array
来初始化字段:
public class Panel {
TextBox A;
TextBox B;
TextBox C;
TextBox D;
TextBox E;
...
public Panel(Field[] fields){
this.fields = fields;
init();
}
public void initA(){}
public void initB(){}
public void initC(){}
public void initD(){}
public void initE(){}
}
我的问题是,如何在不编写许多 if 语句的情况下初始化给定的字段?
我找不到任何解决方案,我现在像这样初始化:
public void init(){
for(int i = 0 ; i < fields.length; i++){
if(fields[i] == Field.A){
initA();
} else if(fields[i] == Field.B){
initB();
} else if(fields[i] == Field.C){
initC();
} else if(fields[i] == Field.D){
initD();
} else if(fields[i] == Field.E){
initE();
} ....
}
}
I have an enum like
public enum Field {
A, B, C, D, E ....;
private Field(){
}
}
I have a class Panel
that takes Field array
to initialize the fields:
public class Panel {
TextBox A;
TextBox B;
TextBox C;
TextBox D;
TextBox E;
...
public Panel(Field[] fields){
this.fields = fields;
init();
}
public void initA(){}
public void initB(){}
public void initC(){}
public void initD(){}
public void initE(){}
}
My question is, how can I initialize the fields that given without writing many if statement?
I can't find any solution and I'm now initializing like this:
public void init(){
for(int i = 0 ; i < fields.length; i++){
if(fields[i] == Field.A){
initA();
} else if(fields[i] == Field.B){
initB();
} else if(fields[i] == Field.C){
initC();
} else if(fields[i] == Field.D){
initD();
} else if(fields[i] == Field.E){
initE();
} ....
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
听起来你的设计可能需要考虑一下。一些建议:
然后你可以迭代数组
你的枚举并调用 init
方法,所以枚举知道如何
进行自己的初始化
初始化并创建一个
您的枚举的映射作为键和
命令作为值。循环
运行命令绕地图旋转
对于每个枚举。
对于第一个项目符号,您可以更改 TextBox 以保存针对它的 Field 类型,例如
所以如果 TextBox 知道它是 A,B ,C,D,E 那么你只需要循环你的 Field[] ,当它找到它的数学 TextBox 时运行初始化代码(可以针对特定的枚举实例存储)。当然,您需要在某个数据结构中注册所有 TextBox 实例,因为您似乎非常反对使用广泛使用的反射 API。
本质上,字段和文本框之间必须存在链接。 Java 无法读懂您的想法,并且无需您告诉它就知道这一点。好吧,至少在 Google 推出他们的心灵感应 API 之前(这可能只适用于 Go……)。这可以基于命名(反射)、硬编码逻辑(if 或开关)或基于状态来完成。对于后者,这意味着将字段与文本框相关联,正如我在上面的构造函数示例中所演示的那样。
Sounds like your design might need to be looked at. A few suggestions:
then you can iterate around the array
of your enums and call the init
method on it, so the enum knows how
to do its own initialization
the initialization and create a
Map of your enum as the key and
the Command as the value. Cycle
round the map running the Command
for each enum.
For the first bullet, you could change the TextBox to hold a Field type against it e.g.
So if TextBox knows it is A,B,C,D,E then you just need to loop around your Field[] and when it finds its mathing TextBox run the init code (which can be stored against the specific enum instance). Of course you will need to register all your TextBox instances in a data structure somewhere, as you seem very set against using the very widely used reflection API.
In essence there has to be a link between the Field and the TextBox. Java cannot read your mind and know this without you telling it. Well, at least until Google unveil their telepathy API (and that would probably only be for Go...). This can be done based on naming (reflection), hardcoded logic (ifs or switches) or based on state. For the latter this means associating the Field with the TextBox, as I have demonstrated with the Constructor example above.
从设计角度来看,我会选择工厂模式、单例模式(基于枚举)和命令模式的组合。我看到一组命令,其中每个命令都特定于给定值。 工厂(单例)是创建此类专用实例的常见模式。 尽管它只是将 if/switch 链移动到工厂中(但允许工厂使用条件检查来创建实例..)。
我不认为我们可以在不使用命名约定和反射/实例化或不引入所有初始化程序共享相同代码的约束的情况下摆脱所有条件检查。
From a design perspective I'd choose a combination of Factory pattern, Singleton pattern (enum based) and Command pattern. I see a set of commands where each command is specific for a given value. A factory (Singleton) is a common pattern to create such specialized instances. Even though it simply moves the if/switch chain into the factory (but factories are allowed use conditional checks in order to create the instances..).
I don't think that we can get rid of all conditional checks without using naming conventions and reflection/instantiation or without introducing the constraint, that all initializers share the same code.
这是一个将 init 方法添加到枚举的代码片段。在每个字段的 init 方法中,您可以调用不同的 initX() 方法之一。使 init 方法抽象可以让编译器提醒您为枚举值定义 init 方法。
Here's a snippet featuring adding the init method to the enum. In each Field's init method you can call one of your different initX() methods. Making the init method abstract gets the compiler to remind you to define your init method for the enum value.
正如 @planetjones 提到的,您可以向枚举类添加一个
init()
方法。 init 方法应返回对其(枚举)类型的已初始化TextBox
的引用。如果您需要将数据传递给初始化器,您可以传递this
,以便它可以检索所需的任何信息。为了解决查找要分配的变量的问题,您可以声明一个 TextBox 数组
,或者在初始化临时数组后分配它们。
当然,您应该声明常量而不是使用幻数。
You can, as @planetjones mentioned, add an
init()
method to your enum class. The init method should return a reference to the initialisedTextBox
of its (enum) type. If you need to pass data to the initialisor you can passthis
so that it can retrieve any information it needs.To get around the problem of finding the variable to assign to, you can either declare an array of
TextBox
esor assign them after you initialised a temporary array.
Of course you should declare constants instead of using magic numbers.
您可以使用 java 反射来循环枚举,但您确实应该研究某种方法来合并所有 initN() 方法。
You could use java reflection to loop through your enum, but you really should look into some way to consolidate all your initN() methods.
为什么你目前的实施很糟糕?仅仅因为长得“丑”?您可以使用 switch 而不是一堆 if:
也许 initA、initB... 中的逻辑非常相似?如果你有 20 个不同的枚举,还有 20 个不同的 init 需要运行,那么改进的空间就很小了......
Why you current implementation is bad? Only because it looks "ugly"? You can use switch instead of bunch of if:
Maybe logic in initA, initB... is very similar? If you have 20 different enums, and 20 different init to run, not much space for improvement...
例如,您可以通过将初始化逻辑移至枚举来做到这一点。有一个初始化方法,它以 TextBox 作为参数并对其进行初始化。
顺便说一句,您最好将 TextBox 变量放在数组中。
编辑
另一种选择是,我经常使用枚举作为一种原型存储。我有一个方法返回一个与特定枚举类型匹配的对象。
如果您不想在枚举中进行初始化,您可以将其移至要返回的对象。对于每个特定的对象,您将有一个单独的初始化。
我担心你是想用这个来追龙。
这么看吧。由于您的问题是“有条件的”,即您必须根据字段的枚举类型进行不同的初始化,因此在某些时候您将不得不使用 ifs 或 switch 语句。
相信没有什么神奇的方法可以解决这个问题,程序应该如何知道你想要做什么?即使使用反射,您也会使用 ifs 等来相应地初始化它。
You could do it, for example, by moving initialization logic to the enum. Have there a method initialize that takes a TextBox as the parameter and initializes it.
BTW you would be better having the TextBox variables in an array.
EDIT
Another option is, what I often is I use an enum as a sort of archetype storage. There I have a method returning an object which matches a certain enum type.
If you do not want to have initialization in enum you could move it to objects you are going to return. There for each particular object you will have a separate initialization.
I am afraid that you are trying to chase the dragon with this one.
Look at it this way. Since the problem of yours is 'conditional', i.e. you have to do a different initialization depending on enum type of a Field, thus at some point you will have to use ifs or switch statement.
Believe there is no magic way around it, how the program should know what you want to do? Even using reflection you will use ifs, etc. to initialize it accordingly.
如果与每个 TextBox 关联的 init 方法非常不同,并且字段列表很小,那么您的方法一点也不坏。另外,如果您通常只实例化这些面板实例之一,那么其他方法实际上弊大于利。
话虽如此,请考虑使用 java.util。枚举映射。之后,您有三个选择:
最佳选择取决于用例。
Your approach is not at all bad if the init methods associated with each TextBox is very different, and the list of Fields is small. Also, if you typically instantiate only one of these Panel instances, the other approaches can actually hurt more than help.
Having said that, consider using a java.util.EnumMap. After that, you have three choices:
initA
, ... using reflection orThe best choice depends on use case.
从这个例子开始:
通过为PanelField定义一个由枚举实现的接口,这个例子可以很容易地变成一个抽象解决方案。 FooPanel 可以用作面板的基类。
Start with this example:
This example can be easily turned into a abstract solution by defining an interface for PanelField, that is implemented by enums. FooPanel can be used as a base class for Panels.
最好将 init 移到枚举中,就像:
虽然这是非常简单的示例,但您可以稍后向构造函数添加任何代码,并根据实际对象本身做出更复杂的决策。
best u move the init into the enum, just like:
Although this is really simple example, you can add any code to the constructor later on and have more complex decisions based on the actual object itself.