我正在开发一个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的方法。
答案 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");
}
}