通用返回对象中不可用的方法

时间:2018-02-01 16:05:32

标签: java

我正在尝试从返回的对象GetDatbaseName()访问方法obj,但它返回错误,表明该方法不可用。

但是,当我对obj进行类型转换时,它正在运行。

String name = ((Oracle)obj).GetDatabaseName();

如何处理这种通用?就像我可以为OracleMongoDB这样的每种返回类型进行类型转换。还有更好的实现吗?

// one class needs to have a main() method
public class HelloWorld
{
  // arguments are passed using the text field below this editor
  public static void main(String[] args)
  {
    Data dt = new Data("Oracle");
    Object obj = dt.GetObject();

    String name = obj.GetDatabaseName();

    System.out.println(name);
  }
}

public class Data
{
    public String _type;

    public Data(String type)
    {
      _type = type;
    }

    public Object GetObject()
    {
      Object obj = null;

      switch(_type)
      {
        case("Oracle"):

        obj = new Oracle("Test");

        break;

        case("MongoDB"):

        obj = new MongoDB("TestCollection");

        break;

      }

      return obj;
    }
}


public class Oracle
{
  public String _databaseName;

  public Oracle(String databaseName)
  {
    _databaseName = databaseName;
  }

  public String GetDatabaseName() { return _databaseName; }
}

public class MongoDB
{
  public String _collectionName;

  public MongoDB(String collectionName)
  {
    _collectionName = collectionName;
  }

  public String GetCollectionName() { return _collectionName; }
}

4 个答案:

答案 0 :(得分:1)

您的问题在以下几行:

Object obj = dt.GetObject();

String name = obj.GetDatabaseName();

就这些行而言,obj是Object类型,它没有被调用的方法;因此,这个问题。这是因为Java是强类型的。

要解决此问题,您需要具有此方法的类型,或使用反射。要使用具有此方法的类型,他们需要从公共父接口继承它,从公共接口实现它。你也可以包装你的对象或其他一些替代品。

在您的情况下,似乎常见的界面是最简单的方法。在这种情况下,每个类都应实现此接口,而不是使用Object,您的引用将是该接口的类型。

public Object GetObject()

会变成

public MyInterface GetObject()

public class Oracle

将是

public class Oracle implements MyInterface

MyInterface将声明方法

public interface MyInterface {
    String GetDatabaseName();
}

注意Java约定,方法应该以小写

开头
public interface MyInterface {
    String getDatabaseName();
}

如果您无法更改代码以实现这些方法,则可以使用" instanceof"测试类类型。

name = (obj instanceof Oracle)?((Oracle)obj).GetDatabaseName():((MongoDB )obj).getCollectionName();

答案 1 :(得分:1)

有两种方法可以解决这个问题,第一种方法是使用通用class,而第二种方法是使用interface,如果您知道类具有相同的方法,第二种方法会更好,而通用的方法是如果类有不同的方法

通用方法

public class DBtest{
    public static void main(String[] args){
        DataBase<Oracle> database = new DataBase<>(Oracle.class);

        Oracle oracle = database.getDataBase();

        System.out.println(oracle.getDatabaseName());
    }
}

class DataBase<T>{
    private T database;

    public DataBase(Class<T> classOfT){
        try {
            database = classOfT.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    public T getDataBase(){
        return database;
    }
}


class Oracle{
    private String _databaseName;

    public Oracle(){
        _databaseName = "test";
    }

    public String getDatabaseName() { return _databaseName; }
}

正如您所看到的,无法定义数据库的名称,您可以编写<T extends Name>这是一个具有getName()setName()方法的接口

接口方法

public class DBtest{
    // arguments are passed using the text field below this editor
    public static void main(String[] args){
        DataBase database = new DataBase(new Oracle("test"));

        DatabaseName databaseName = database.getDataBase();

        System.out.println(databaseName.getName());
    }
}

interface DatabaseName {
    String getName();
}

class DataBase{
    private DatabaseName databaseName;

    public DataBase(DatabaseName databaseName){
        this.databaseName = databaseName;
    }

    public DatabaseName getDataBase(){
        return databaseName;
    }
}


class Oracle implements DatabaseName {
    private String _databaseName;

    public Oracle(String name){
        _databaseName = name;
    }

    public String getName() {
        return _databaseName;
    }
}

class MongoDB implements DatabaseName {
    private String _databaseName;

    public MongoDB(String name){
        _databaseName = name;
    }

    public String getName() {
        return _databaseName;
    }
}

显然DatabaseName是接口的错误名称,但它是两个类中唯一相同的方法,因此将其称为有意义。关于接口的好处是,只要您知道方法名称,就不必大肆宣传class使用的内容。

答案 2 :(得分:1)

您必须创建一个接口,然后使用getDatabaseName()方法。然后您的对象Oracle和MongoDB必须实现该接口。 你想要做的是类似于AbstractFactory Pattern。你应该谷歌。

public interface MyDbInterface {
    String getDatabaseName();
}
public class HelloWorld {
    // arguments are passed using the text field below this editor
    public static void main(String[] ){
        MyDbInterface dt = DataFactory.create("Oracle");
        String name = dt.getDatabaseName();

        System.out.println(name);
    }
}

public final class DataFactory{

    private DataFactory(){
        super();
    }

    public static MyDbInterface create(String type){
        MyDbInterface obj = null;

        switch(type) {
            case("Oracle"):
                obj = new Oracle("Test");
            break;
            case("MongoDB"):
                obj = new MongoDB("TestCollection");
            break;

        }
        return obj;
    }
}


public class Oracle implement MyDbInterface{
    public String databaseName;

    public Oracle(String databaseName){
        databaseName = databaseName;
    }

    @Override
    public String getDatabaseName() { 
        return databaseName; 
    }
}

public class MongoDB implement MyDbInterface{
    public String collectionName;

    public MongoDB(String collectionName){
        collectionName = collectionName;
    }

    public String getCollectionName() { 
        return collectionName; 
    }

    @Override
    public String getDatabaseName() { 
        return getCollectionName(); 
    }
}

我来自C#,请查看java风格指南。 ;)

答案 3 :(得分:0)

您应该考虑代码的设计。您需要使用基本的OOP主体来解决问题。有几种方法可以解决您的问题,比如使用interface / generics等。这里我给出了一个这样的例子。

public class HelloWorld {

    public static void main(String[] args) {
        Data dt = new Data("Oracle");
        DataBase obj = dt.GetObject();
        String name = obj.getDatabaseName();
        System.out.println("Name : "+name);
    }
}

class Data {
    public String _type;

    public Data(String type) {
        _type = type;
    }

    public DataBase GetObject() {
        DataBase dataBase=null;
        switch (_type) {
        case "Oracle":
            dataBase = new Oracle(); 
            break;
        case "Mongo":
            dataBase = new MongoDb(); 
            break;

        }
        return dataBase;
    }
}

interface DataBase {
    String getDatabaseName();
}

class Oracle implements DataBase {
    public String getDatabaseName() {
        return "Oracle";
    }
}

class MongoDb implements DataBase {
    public String getDatabaseName() {
        return "Mongo";
    }
}

编辑:

这是解决问题的另一种方法。我相信这种方法可以解决您的问题。

public class HelloWorld {

    public static void main(String[] args) {
        Data<Oracle> dt = new Data<Oracle>("Oracle");
        Oracle obj = dt.getObject();
        String name = obj.getDatabaseName();
        System.out.println("Name : "+name);
    }
}

class Data<T> {
    public String _type;

    public Data(String type) {
        _type = type;
    }

    public T getObject() {
        Object dataBase=null;
        switch (_type) {
        case "Oracle":
            dataBase = new Oracle(); 
            break;
        case "Mongo":
            dataBase = new MongoDb(); 
            break;

        }
        return (T)dataBase;
    }
}


class Oracle  {
    public String getDatabaseName() {
        return "Oracle";
    }
}

class MongoDb {

}