从不同类型的实例调用相同的方法名称

时间:2014-04-05 08:52:38

标签: java dynamic polymorphism

我有一些外部公司的库,我想使用这个API。我尝试实现调用此API,我的逻辑应该调用相同的方法名称。我有重复的代码,我想避免这样做。我是初学者,接口,多态等主题对我来说有点困难。

public void modPeople(Object person)
{
 if (person instanceof com.company.persontype1)
 {
  com.company.persontype1 fireman = (com.company.persontype1) person; 
  String name = fireman.getName();

     if (name!=null ) {
     ...
      fireman.set_name();
      fireman.save();
     }

     permissions  = fireman.get_Permissions();
     ...
  permissions = fixperm (permissions);

  fireman.set_Permissions();
 };

 if (person instanceof com.company.persontype2)
 {
  com.company.persontype2 nurse = (com.company.persontype2) person; 
  String name = nurse.getName();

     if (name!=null ) {
     ...
      nurse.set_name();
      nurse.save();
     }

     permissions  = nurse.get_Permissions();
     ...
  permissions = fixperm (permissions);

  nurse.set_Permissions();
 };
}

1 个答案:

答案 0 :(得分:0)

首先,我要提一下,您在问题中请求的方法称为"Duck Typing"。通常这种技术在Java中是可能的(参见下面的例子),但它并没有在Java中广泛使用。可能存在性能命中等。相反,引入适当的继承/接口级别会好得多。

此外,所提供的示例也没有正确处理异常等。这只是一种快速且非常肮脏的技术演示"。随意根据您的需求进行调整。

它的Java7(对于多捕获条款,你可以轻松地重构它)。

ISomeIterface.java(它包含由您的"错误代码"中使用的类实现的所有常用方法):

package org.test;

public interface ISomeInterface {
  public String getName();
  public void setName(String _name);
  public void save();
  // specify other common methods
}

ReflectCaller.java:

package org.test1;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.NoSuchElementException;

import org.test.ISomeInterface;

public class ReflectCaller {

  private final Method[] methods = ISomeInterface.class.getDeclaredMethods();
  private final Map<Class<?>, Method[]> maps = new HashMap<Class<?>, Method[]>();

  public void inspectClass(Class<?> _clazz) throws NoSuchMethodException, SecurityException {
    final Method[] ms = new Method[methods.length];
    int i = 0;
    for(final Method m: methods) {
      ms[i] = _clazz.getMethod(m.getName(), m.getParameterTypes());
      i++;
    }
    maps.put(_clazz, ms);
  }

  public ISomeInterface wrapper(Object _obj) {
    final Method[] ms = maps.get(_obj.getClass());
    // To be replaced by guava's Preconditions.checkState()
    if (ms == null)
      throw new NoSuchElementException(String.format("Class %s is unregistered", _obj.getClass().getName()));
    return new SomeInterfaceImpl(_obj, ms);
  }

  private static class SomeInterfaceImpl implements ISomeInterface {
    private final Object obj;
    private final Method[] ms;

    public SomeInterfaceImpl(Object _obj, Method[] _ms) {
      ms = _ms;
      obj = _obj;
    }

    @Override
    public String getName() {
      try {
        return (String) ms[0].invoke(obj);
      } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
        throw new RuntimeException(e);
      }
    }

    @Override
    public void setName(String _name) {
      try {
        ms[1].invoke(obj, _name);
      } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
        throw new RuntimeException(e);
      }
    }

    @Override
    public void save() {
      try {
        ms[2].invoke(obj);
      } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
        throw new RuntimeException(e);
      }
    }
  }
}

测试类ReflectTest.java。请注意,ReflectTest.Test和ReflectTest.Test2类与ISomeInterface具有相同的方法但不实现它们,它们完全独立于该接口并且彼此独立。

package org.test2;

import org.test.ISomeInterface;
import org.test1.ReflectCaller;

public class ReflectTest {
  private final ReflectCaller rc;
  ReflectTest(Class ... _classes) throws NoSuchMethodException, SecurityException {
    rc = new ReflectCaller();
    for(final Class c: _classes)
      rc.inspectClass(c);
  }

  void callSequence(Object _o) {
    // this function demonstrates the sequence of method calls for an object which has "compliant" methods
    ISomeInterface tw = rc.wrapper(_o);
    tw.setName("boo");
    System.out.printf("getName() = %s\n", tw.getName());
    tw.save();
  }

  public static class Test {
    public String getName() {
      System.out.printf("%s.getName()\n", getClass().getName());
      return "boo";
    }
    public void setName(String _name) {
      System.out.printf("%s.setName(%s)\n", getClass().getName(), _name);
    }
    public void save() {
      System.out.printf("%s.save()\n", getClass().getName());
    }
  }

  public static class Test2 {
    public String getName() {
      System.out.printf("%s.getName()\n", getClass().getName());
      return "boo2";
    }
    public void setName(String _name) {
      System.out.printf("%s.setName(%s)\n", getClass().getName(), _name);
    }
    public void save() {
      System.out.printf("%s.save()\n", getClass().getName());
    }
  }

  public static void main(String[] args) {
    ReflectTest rt;
    try {
      rt = new ReflectTest(Test.class, Test2.class);
    } catch (NoSuchMethodException | SecurityException e) {
      System.out.println(e);
      System.exit(2);
      return;
    }

    rt.callSequence(new Test());
    rt.callSequence(new Test2());
  }
}