是否可以将代码存储在可以从另一个对象运行的对象中?

时间:2019-02-03 13:57:29

标签: java

在Java中,

class BlaBlaThirty extends Parent {
    void foo(String s, int i) {}
}

class BlaBlaTwentyNine extends Parent {
    void foo(int i, Bla a, This t, Other o) {}
}

class BlaBlaFive extends Parent {
    void foo(Bla a, Other o) {}
}

...

许多不同的类都带有foo()方法。

ArrayList<Object> arr;
arr.add(blablai);
arr.add(blablaj);
arr.add(blablak);
...

array arr包含许多对象,这些对象是这些类的实例。 问题在于所有这些foo()方法都没有相同的参数。如何使用正确的参数调用这些方法?

arr.get(i).foo(?,?,?);

我的解决方案:

所有foo方法都有一个ArrayList params参数,该参数包含所有需要的参数作为Object:

class BlaBlaX {
     void foo(ArrayList<Object> params) {}
}

然后,在包含foo的类中添加foo()所需变量的变量名称。在调用foo()之前,我先调用getFooParams():

class BlaBlaTwentyTwo extends Parent {

    ArrayList<Object> getFooParams() {

        ArrayList<String> p;
        p.add("i");
        p.add("banana");
        p.add("volkswagen");

        return p;
    }

    void foo(ArrayList<Object> params) {
        Int i = (int) params.get(0);
        Fruit banana = (Fruit) params.get(1);
        Car volkswagen = (Car) params.get(2);
    }
}

调用foo()方法的对象包含foo()所需的所有变量:

class ObjCallingFoo {
   int i;
   Fruit banana;
   car volkswagen;

   //see below for what is here to call foo()
}

import java.lang.reflect.Method;
import java.lang.reflect.Field;

p = arr.get(i).getFooParams();
int size = p.size();
ArrayList<Object> arrParams = new ArrayList<>();
for (int i = 0; i < size; i++) {
    String variableName = p.get(i);
    Field field = objCallingFoo.getClass.getField(variableName);
    arrParams.add(field);
}

我现在可以使用正确的参数调用foo了:

arr.get(i).foo(arrParams);

我还没有测试。 您如何看待?

是否可以将代码存储在可以从另一个对象运行的对象中?

OR

如果我们不知道要作为参数传递给调用对象的方法的具体成员变量是什么,那么如何调用带有另一个对象的参数的方法?

5 个答案:

答案 0 :(得分:1)

您需要一个抽象,其中包括调用以及的特定方法。这就是 Strategy Command 设计模式所能做的。

答案 1 :(得分:0)

通常,您可以使用instanceof

Object parent = obj.get(i);

if(parent instanceof BlaBlaThirty)
    ((BlaBlaThirty)parent).foo(?,?);
else if(parent instanceof BlaBlaTwentyNine)
    ((BlaBlaTwentyNine)parent).foo(?,?,?);
else if(parent instanceof BlaBlaFive )
    ((BlaBlaFive )parent).foo(?,?);

附言。将所有这些对象保存在一个列表中是不好的。您的代码组织确实应该重构!

答案 2 :(得分:0)

您可以在Parent中使用不同的构造函数和基本方法foo()。 然后,您可以在每个类中覆盖它,并对字段进行不同的操作。 但是我认为这是一个选择,但是也许您应该以另一种方式重构代码/抽象/继承。

class Parent {
   void foo(){}
}

class BlaBlaThirty extends Parent {
//Contructor with String s, int i

void foo() {
   //Do something here with fields  String s, int i
}

class BlaBlaTwentyNine extends Parent {
//Contructor with int i, Bla a, This t, Other o

void foo() {
  //Do something here with fields int i, Bla a, This t, Other o
}

class BlaBlaFive extends Parent {
//Constructor Bla a, Other o
void foo() {
  //Do something here with fields Bla a, Other o
}

...

许多不同的类都带有foo()方法。

ArrayList<Parent> parent;
parent.add(blablai);
parent.add(blablaj);
parent.add(blablak);
...

parent.foo()
parent.foo()
parent.foo()

答案 3 :(得分:0)

您可能要使用界面:

public interface Blainterface{
   public void foo();
}

public class BlaBlaTwentyNine extends Parent implements Blainterface {
     public void foo() {}
}
....
ArrayList<Blainterface> obj;
obj.add(blablai);
obj.add(blablaj);
obj.add(blablak);

//now you can acces it like 

obj.get(2).foo();

它变得更好。您可能有一个没有实现该接口的类,但是具有一个看起来相同的方法:

public interface Blainterface{
    public void foo();
}

public class Blubclass{
    public void bar(){ //note its bar here and not foo()!!!
      //do something cool!  
    }
}
//...

ArrayList<Blainterface> obj;
obj.add(blablai);
obj.add(blablaj);
obj.add(blablak);
Blubclass blub = new Blubclass(); //note that blub has no foo() method.
obj.add(blub::bar);

//And that call will work too:
obj.get(3).foo(); //this will call bar() in the Blubclass.

现在,使用具有不同参数的东西进一步前进:

public interface Blainterface{
    public void foo();
}

public class Bazclass{
    public void baz(Sting name){ //note its baz here and not foo() and it has a parameter!!!
      //do something cool!  
    }
}
//...

ArrayList<Blainterface> obj;
obj.add(blablai);
obj.add(blablaj);
obj.add(blablak);
Bazclass baz = new Bazclass(); //note that baz has no foo() method and a parameter.
obj.add(()->baz.baz("name"));//mapping of parameters

//And that call will work too:
obj.get(3).foo(); //this will call baz("name") in the Bazclass. Even though we use a different method name and parameters for the call.

您只需要在调用方法时在接口中定义要使用的签名。 而且,您必须告诉Java如何映射参数(无法猜测)。

答案 4 :(得分:0)

最后我会做什么,

class FooParamsNeeded {
    public boolean blaBlaI;
    public boolean blaBlaJ;
    public boolean i;
    public boolean blaBlaK;
    public boolean banana;
    public boolean blaBlaL;
    public boolean volkswagen;
    public boolean blaBlaM;
    ...
}

// ------------在foo()所在的对象中,有一个特定的getFooParams()方法,其参数需要设置为true ---------- < / p>

FooParamsNeeded getFooParams() {
    FooParamsNeeded fpn = new FooParamsNeeded();
    fpn.i = true;
    fpn.banana = true;
    fpn.volkswagen = true;
    return fpn;
}

// --------------------

class FooParams {
    public BlaBlaI blaBlaI;
    public BlaBlaJ blaBlaJ;
    public int i;
    public BlaBlaK blaBlaK;
    public Fruit banana;
    public BlaBlaL blaBlaL;
    public Car volkswagen;
    public BlaBlaM blaBlaM;
    ...
}

// -------在对象中调用其他对象的foo()方法的位置-----

FooParams setFooParams(FooParamsNeeded fpn) {
    FooParams fp = new FooParams();
    if (fpn.blaBlaI)
        fp.blaBlaI = blaBlaI;
    if (fpn.blaBlaJ)
        fp.blaBlaJ = blaBlaJ;
    if (fpn.i)
        fp.i = i;
    if (fpn.blaBlaK)
        fp.blaBlaK = blaBlaK;
    if (fpn.banana)
        fp.banana = banana;
    if (fpn.blaBlaL)
        fp.blaBlaL = blaBlaL;
    if (fpn.volkswagen)
        fp.volkswagen = volkswagen;
    if (fpn.blaBlaM)
        fp.blaBlaM = blaBlaM;
    ...

    return fp;
}

FooParamsNeeded fpn = arr.get(i).getFooParams();
FooParams fp = setFooParams(fpn);
arr.get(i).foo(fp);

// -------------------------------------

我认为我应该有10-15个可能的不同参数,所以setFooParams()中应该有10-15个if语句。