【问题标题】:Java platform-dependent class inheritanceJava 平台相关的类继承
【发布时间】:2014-12-26 18:45:40
【问题描述】:

我开发了一个可以在两个不同平台上运行的 Java 库。要打印消息,一个平台使用printA(str) 方法,而另一个平台使用printB(str) 方法。在 C++ 中,我会创建一个静态方法:

public static void print(string str)
{
    #ifdef platformA
        printA(str);
    #else
        printB(str);
    #endif
}

由于 Java 没有#ifdef,因此它成为一项棘手的任务。我开始研究用静态方法覆盖抽象类,但不确定我是否走对了方向。最优雅的方法是什么?


编辑:在 Andy Thomas 的回答下(谢谢!)我找到了适合我的解决方案。唯一的缺点 - 它必须在启动时初始化。下面是代码。 公共库:

//interface is only for internal use in Output class
public interface IPrintApi
{
    public void Print(String message);
}

public abstract class Output
{
    private static IPrintApi m_api;
    public static void SetPrintAPI(IPrintApi api)
    {
        m_api=api;  
    }

    public static void MyPrint(String message)
    {
        m_api.Print(message);
    }
}

该函数的调用在普通库和平台代码中是一样的:

public class CommonTest 
{
    public CommonTest()
    {
        Output.MyPrint("print from library");
    }
}

每个平台的代码都必须具有特定于平台的接口实现,例如平台A(对于B是相同的):

public class OutputA implements IPrintApi
{
    public void Print(String message)
    {
        //here is our platform-specific call
        PrintA(message);
    }
}

用法:

public class AppPlatformA
{
        public static void main(String[] args)
        {
            // point the abstract Output.Print function to the available implementation
            OutputA myPrintImpl = new OutputA();
            Output.SetPrintAPI(myPrintImpl);
            // and now you can use it!
            Output.MyPrint("hello world!");
        }
}

【问题讨论】:

  • [stackoverflow.com/questions/228477/…我想这对你有帮助。
  • 这不是运行时检测的问题,更多的是避免编译时问题的代码设计:我在platformB中使用库时没有定义printA,反之亦然...跨度>

标签: java import conditional conditional-compilation


【解决方案1】:

使用常量表达式:

private static final boolean PLATFORM_A = true;

 public static void print(string str)
  {
    if(PLATFORM_A )
    {
       printA(str);
    }
    else
    {
      printB(str);
    }
  }

【讨论】:

  • 持续使用并不是很好。我在两个平台上同时使用的库中使用它,即 Windows 和 Android。而且我不想每次都更改通用代码中的 const ......
  • 那么你可以去 System.getEnv() 并根据环境执行。
【解决方案2】:

这段代码呢?

    public class Example {

    public static void main(String[] args) {
        print();
    }

    public static void print() {
        String platform = System.getProperty("os.name");
        switch (platform) {
        case "Windows 7":
            System.out.println("This is Windows 7");
            break;
        case "Windows XP":
            System.out.println("This is Windows XP");
            break;
        }
    }
}

【讨论】:

  • 谢谢,但问题更多是关于不同的 API 调用,而不是如何检测平台。
【解决方案3】:

您可以使用strategy pattern

定义一次接口,然后在特定于操作系统的类中实现它。

    public interface IPlatformAPI {
        public void print( String str );
    }

    public class WindowsPlatformAPI implements IPlatformAPI {
        public void print( String str ) { ... }
    }

    public class MacPlatformAPI implements IPlatformAPI {
        public void print( String str ) { ... }
    }

    public class LinuxPlatformAPI implements IPlatformAPI {
        public void print( String str ) { ... }
    }

    public class PlatformAPI {
       public static IPlatformAPI getPlatformAPI() {
          // return one of the platform APIs
          // You can use System.getProperty("os.name") to choose the implementation
       }
    }

【讨论】:

  • 谢谢。听起来很有趣。唯一不清楚的一点是如何在 PlatformAPI 类中引用三个不兼容的类,由于不同的依赖于植物形式的包含而不能一起编译。并且这种情况下的打印方法不能被污化为静态...
  • 首先,确认您不能编译所有针对特定平台的 Java 代码。如果不能,一种选择是在运行时使用Class.forName()Class.newInstance() 加载适当的类。顺便说一句,欢迎来到 StackOverflow。您可以通过单击左侧的复选标记接受您认为最佳的答案。您可以投票多个您认为有用的答案。
  • 我接受这个作为答案。我不得不修改一下你的例子,但现在它可以按我的意愿工作,而且对我来说看起来不错。稍后我会发布一个示例代码。
猜你喜欢
  • 2018-02-09
  • 1970-01-01
  • 2021-05-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-25
  • 2015-11-16
相关资源
最近更新 更多