[英]Java - Can I cast a variable modification from one class to another?
Say I have in class A
: 说我在A
班:
int a = 1, b = 2, c = 3;
Now, say in class B
I have a function: 现在,在B
级说我有一个功能:
public int void reset(String intName, A classA) {
...
}
Within reset()
if I do reset('c', classA)
, then I want c
in classA
to be reset. 在reset()
如果我reset('c', classA)
,那么我希望重置classA
c
。 If I do a reset('b', classA)
, then I want b
in classA
to be reset and so forth. 如果我进行reset('b', classA)
,那么我希望重置classA
b
等等。 I'm not sure if this is possible, but I need this to kill off units of different classes in a game. 我不确定这是否可行,但我需要这个来消灭游戏中不同类别的单位。
This is possible through reflection. 这可以通过反思来实现。 But since reflection is slow, I advise you not to try reflection immediately. 但由于反思很慢,我建议你不要立即尝试反思。 Try something else first. 先尝试别的。 Why can't you just do: 你为什么不能这样做:
someObjectOfA.a = some value;
someObjectOfA.b = some value;
someObjectOfA.c = some value;
Anyway, here is the solution using reflection: 无论如何,这是使用反射的解决方案:
public static void reset(String name, A a) throws NoSuchFieldException, IllegalAccessException {
Class<A> clazz = A.class;
Field f = clazz.getField(name);
f.set(a, 0);
}
Note that a
, b
and c
must be declared public
or a NoSuchFieldException
will be thrown. 请注意,必须将a
, b
和c
声明为public
, NoSuchFieldException
将抛出NoSuchFieldException
。
If you don't want to expose your fields, you can add setters like this one: 如果您不想公开字段,可以添加如下设置:
public void setA(Integer value) {
a = value;
}
Then the reset
method will be: 然后reset
方法将是:
public static void reset(String name, A a) throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
Class<A> clazz = A.class;
Method m = clazz.getMethod("set" + name.toUpperCase(), Integer.class);
m.invoke(a, 0);
}
There are many options here, even without using reflection (ie dynamically modifying arbitrary properties of the object by names specified at runtime). 这里有很多选项,即使不使用反射(即通过运行时指定的名称动态修改对象的任意属性)。 The simplest is to simply have A
be responsible for translating from the specified key to the corresponding variable: 最简单的是让A
负责从指定的键转换为相应的变量:
public class A {
private static int a = 1, b = 2, c = 3;
public void reset(String key) {
switch(key) {
case "a": a = 0;
break;
case "b": b = 0;
break;
case "c": c = 0;
break;
default:
break;
}
}
}
public class B {
public int void reset(String intName, A obj) {
obj.reset(intName);
}
}
This leads to repetitive code though, and it's easy to make mistakes, especially as you add new fields to A
. 这会导致重复的代码,并且很容易出错,尤其是当您向A
添加新字段时。
A better option would be using a Map
to dynamically map the property names to their values: 更好的选择是使用Map
将属性名称动态映射到它们的值:
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class A {
private static Map<String, Integer> map = new HashMap<>();
static {
map.put("A", 1);
map.put("B", 2);
map.put("C", 3);
}
public Map<String, Integer> getGameProperties() {
return Collections.unmodifiableMap(map);
}
public void reset(String key) {
map.put(key, 0);
}
}
public class B {
public int void reset(String intName, A obj) {
obj.reset(intName);
}
}
This handles the property declaration and key mapping in a single step, so that fixes the issue of the repetitive, error-prone code. 它在一个步骤中处理属性声明和键映射,从而修复了重复的,容易出错的代码的问题。 It does potentially affect the external interface of the class now since you got rid of the individual fields and replaced them with a Map
. 它现在可能会影响类的外部接口,因为您删除了各个字段并将其替换为Map
。 That's of course a good reason to keep your fields private
and use getters/setters instead, since getters can be updated to look at a Map
without changing the external API of class A
. 这当然是保持字段private
并使用getter / setter的一个很好的理由,因为可以更新getter以查看Map
而无需更改A
类的外部API。
I would design my class A like this: 我会像这样设计我的A班:
class A
{
public enum UnitType { TANK, TRIKE, COMMANDO };
public void reset (UnitType type);
//or even:
public void reset (Set<UnitType> types);
}
So class B could call: 所以B级可以打电话:
a.reset(UnitType.TANK);
or in the Set
case 或者在Set
情况下
a.reset(EnumSet.of(UnitType.TANK, UnitType.COMMANDO));
or 要么
a.reset(EnumSet.allOf(UnitType.class));
You can still choose in class A
how to keep track of the counts, without influencing the interface to class B
您仍然可以在class A
选择如何跟踪计数,而不会影响到class B
的接口
For example, class A can use a Map
internally to keep track of the counts (which seems a good idea), but also fields, or any other method. 例如,A类可以在内部使用Map
来跟踪计数(这似乎是一个好主意),但也可以使用字段或任何其他方法。
Why not just to have a something like setter in class A if you really want to reset it from other class? 如果你真的想从其他类中重置它,为什么不在A类中设置类似setter的东西呢?
Say I have in class A: 说我在A班:
int a = 1, b = 2, c = 3;
public void resetA()
{
this.a = 0;
}
public void resetB()
{
this.b = 0;
}
public void resetC()
{
this.c = 0;
}
or 要么
int a = 1, b = 2, c = 3;
public void resetAll()
{
this.c = 0;
this.a = 0;
this.b = 0;
}
i just can't think for now how to make a good coding for it's flexibility but it can reset you're value even from the other class if you like 我现在想不出如何为它的灵活性做出良好的编码,但如果你愿意,它可以重置你的价值
Try this. 尝试这个。 No need to write setter method for each field. 无需为每个字段编写setter方法。
try
{
Field field = classA.getClass().getDeclaredField(intName);
field.setAccessible(true);
Object value = field.get(classA);
System.out.println(" val "+ value);
field.set(classA, 0);//Reset to zero
value = field.get(classA);
System.out.println(" val "+ value);
} catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.