强制我的库的用户实现接口或扩展抽象类

时间:2017-03-13 16:40:23

标签: java android android-library aar

我正在开发一个android库(.aar),我想知道是否有可能,如标题所示,强制用户实现接口或扩展我的库的抽象类。

我已经知道我可以在我的图书馆中使用这样的课程了:

public class MyLibrary
{
    public interface VariablesInterface
    {
        void createVariables();
    }

    private static VariablesInterface vi = null;

    public void setVariablesInterface(VariablesInterface v)
    {
        vi = v;
    }

    private static void SomeWork()
    {
        if (vi == null)
        {
            throw new RuntimeException("You noob.");
        }
        else
        {
            // do work
        }
    }
}

库在某些时候“单独”工作,当它到达SomeWork()时,如果接口未实现,它将崩溃,但这只能在运行时看到。

在编译用户的应用程序时有没有办法解决这个问题?

目标是避免用户忘记他必须实现这一点,而不必在文档中写入它,并希望用户可能会阅读它。

感谢阅读!

修改

我认为这个问题需要一些改进和背景。 该库的目的是提供创建管理偏好的变量的类,例如, :

public class VarPreferenceBoolean extends VarPreference
{
    private boolean defaultValue;

    public VarPreferenceBoolean(String key, boolean defaultValue)
    {
        super(key, true);
        this.defaultValue = defaultValue;
    }

    public void setValue(Context context, boolean value)
    {
        SharedPreferences.Editor e = context.getSharedPreferences(PropertiesManager.preferenceFileName, Context.MODE_PRIVATE).edit();
        e.putBoolean(key, value);
        e.commit();
    }

    public boolean getValue(Context context)
    {
        readPropFile(context);
        SharedPreferences sp = context.getSharedPreferences(PropertiesManager.preferenceFileName, Context.MODE_PRIVATE);
        return sp.getBoolean(key, defaultValue);
    }
}

同样适用于int,string等。 在超类中,我将每个VarPreference添加到List中以使库确认所有可用变量。 请注意getter中的readPropFile

然后,用户在他的项目中使用这样的库:

public class Constants
{
    public static final VarPreferenceInt     FILETYPE;
    public static final VarPreferenceInt     DATAMODE;
    public static final VarPreferenceString  URL_ONLINE;
    public static final VarPreferenceBoolean UPDATING;
    public static final VarPreferenceLong    LAST_UPDATE;

    static
    {
        FILETYPE = new VarPreferenceInt("FileType", MyFile.FileType.LOCAL.getValue());
        DATAMODE = new VarPreferenceInt("DataMode", DataProvider.DataMode.OFFLINE.getValue());
        URL_ONLINE = new VarPreferenceString("UrlOnline", "http://pouetpouet.fr");
        UPDATING = new VarPreferenceBoolean("Updating", false);
        LAST_UPDATE = new VarPreferenceLong("LastUpdate", 0L);
    }
}

现在,当用户调用访问者时,readPropFile将首先搜索是否存在.properties文件,并相应地修改首选项,如果它找到了VarPreference列表与文件属性之间的匹配项。然后它将删除该文件,访问者将返回该值。

这就是今天的情况。

现在我们想要另一个应用程序(让我们说Pilot)能够获取用户应用程序的VarPreferences(比如说客户端)。两者都实现了库。

Pilot发送一个Intent,要求提供Client的VarPreference列表,另外输入Client的包名。 库接收意图,验证包名,如果它是客户端它发送回列表。

问题是,如果客户端尚未启动,则不存在任何VarPreference,并且列表为空。

我需要强制用户在我的库知道的方法中创建他的VarPreference,以便能够随时调用它,并在必要时创建用户的VarPreferences。

希望这更清楚!

修改

我和一位同事一起重新讨论了所有这一切,它只是打击了我们所有这些堆栈都被联系起来。

我没有很好地解释,即使我说过,我也没有考虑到这一点:一切都需要从图书馆完成。 因此,即使我给库提供了一个接口,应用程序也必须首先运行并调用这种做法,以便让库单独工作。

我们现在正朝内省方向前进。 (这是目标,可能不可能......) 库中将有一个抽象类,使用抽象方法,用户将放置所有VarPreferences创建。用户必须扩展此类并调用该方法以创建其VarPreferences。 在库中,方法将通过内省搜索抽象类的子项,创建此子项的实例并调用将创建VarPreferences的方法。

2 个答案:

答案 0 :(得分:0)

我会将抽象类和接口留在主库中,并通过类加载器从另一个加载代码的其余部分。 JDBC的工作原理如下。

答案 1 :(得分:0)

  

在编译用户的应用程序时有没有办法解决这个问题?

我认为无法强制编译失败。但是,如果强制它们在构造函数中提供VariablesInterface,则它将立即失败。将VariablesInterface设为final并仅在构造函数中初始化它:

 public class MyLibrary {
     private final VariablesInterface vi;

     public MyLibrary(VariablesInterface vi) {
        if (vi == null) {
            throw new IllegalArgumentException("vi can't be null");
        }
        this.vi = vi;
     }
     ...

如果您无法更改构造函数,那么您还可以向任何SomeWork公共方法添加某种配置检查方法,以确保vi布线已正确完成,但这需要小心编程以确保涵盖所有公共方法。

public void somePublicMethod() {
    checkWiring();
    ...
}

private void checkWiring() {
    if (vi == null) {
        throw new IllegalStateException("vi needs to be specified");
    }
}