我正在使用Djinni在安卓和ios之间共享一些大型c++代码库。各种组件之一(让我们称之为Foo!)在android和ios上有不同的实现。Foo是一个接口,c++代码使用它,而不需要了解它的内部结构。
不过,android (FooAndroid)还有一些额外的方法,安卓客户端可以使用这些方法来修改组件的行为,而这些方法只对android平台有意义。
这使djinni变得复杂,因为缺乏接口继承。我想出了一种解决方案,它依赖于这样一个事实,即FooAndroid可以子类两个不同的djinni接口,它们的大多数方法都具有相同的签名,但结果并不理想。
这是djinni接口描述:
foo = interface +c {
static create() : foo;
doSomething();
}
foo_android = interface +c {
static create() : foo_android;
doSomething();
doAnotherThing();
asFoo(): foo;
}
bar = interface +c {
static create() : bar;
useFoo(f: foo);
}您将注意到Bar --一个只需要访问Foo实例的组件。
然后以这种方式实现生成的接口:
// Foo android implementation:
class FooAndroidImpl : public Foo, public FooAndroid {
public:
void doSomething() override { LOGI("do something"); }
void doAnotherThing() override { LOGI(" do something"); }
std::weak_ptr<Api::Foo> fooSelfReference;
std::shared_ptr<Api::Foo> asFoo() override { return fooSelfRef.lock(); }
};
// instance creation methods:
std::shared_ptr<FooAndroidImpl> createImpl() {
auto p = std::make_shared<FooAndroidImpl>();
p->fooSelfRef = p;
return p;
}
std::shared_ptr<FooAndroid> FooAndroid::create()
{
return createImpl();
}
std::shared_ptr<Foo> Foo::create()
{
return createImpl();
}
// Bar implementation:
class BarImpl : public Bar {
public:
void useFoo(const std::shared_ptr<Foo> & f) override { f->doSomething(); }
};
std::shared_ptr<Bar> Bar::create()
{
return std::make_shared<BarImpl>();
}这样,我就可以在java中使用FooAndroid和Bar:
FooAndroid fooAndroid = FooAndroid.create();
fooAndroid.doAnotherThing();
Bar bar = Bar.create();
bar.useFoo(fooAndroid.asFoo());这是可行的,但它是丑陋的,我必须手动定义两个几乎相同的djinni接口,而且我仍然不确定在对象的生命周期中存储该weak_ptr的所有含义。
我觉得我在滥用吉尼的目的和模式,所以也许有更好的方法来达到我想要做的事情?
发布于 2018-05-10 03:50:21
Djinni不支持接口继承,因此这里没有很好的答案。在Dropbox中,这种情况并不常见,我们通常通过将Android/iOS特定的方法添加到单个接口,并使用存根来实现这些方法,从而在另一个平台上抛出异常。不过,我们通常会遇到相反的情况,即实现是用Java/ObjC实现的。
如果您不喜欢这种方法,并且不喜欢方法复制和多重继承,我认为我推荐的另一种方法是使用相关的子对象。例如,有一个带有getAndroidStuff()方法的Foo接口,该方法返回一个只包含Android特定方法的FooAndroid接口。FooAndroid对象可以在内部保存对具有所有功能的FooImpl对象的引用,并将方法转发给它。
这里似乎更广泛的问题是,这些方法的具体平台究竟是什么?如果实现是跨平台的,但只需要在一个平台上使用,那么只让一个C++类存在并不有害,而未使用的方法是不危险的。如果在C++中有特定于平台的代码,那么事情会变得有点尴尬,因为这不是Djinni的设计目标。不过,我认为这种特殊情况需要一个不同于一般情况下的接口继承的解决方案。
https://stackoverflow.com/questions/50087146
复制相似问题