Android — альтернатива наследования интерфейса с Джинни

Я использую Djinni, чтобы поделиться большой базой кода C ++ между Android и IOS. Один из различных компонентов (назовем его Foo!!!) имеет разные реализации на Android и IOS. Foo это интерфейс, который использует код c ++ без необходимости что-либо знать о его внутренностях.

Реализация Android хотя (FooAndroid), имеет некоторые дополнительные методы, которые клиент Android может использовать для изменения поведения компонента способами, имеющими значение только для платформы Android.

Это усложняет работу с джиннами из-за отсутствия наследования интерфейса. Я придумал своего рода решение, которое опирается на тот факт, что FooAndroid может создать подкласс двух разных интерфейсов 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>();
}

Затем я могу использовать FooAndroid и Bar в Java следующим образом:

FooAndroid fooAndroid = FooAndroid.create();
fooAndroid.doAnotherThing();
Bar bar = Bar.create();
bar.useFoo(fooAndroid.asFoo());

Это работает, но это уродливо, я должен вручную определить два почти идентичных интерфейса djinni, и я до сих пор не уверен во всех последствиях сохранения этого weak_ptr для жизненного цикла объекта.

Я чувствую, что злоупотребляю целью и моделью Джинни, так что, может быть, есть лучший способ добиться того, что я пытаюсь сделать?

1

Решение

Джинни не поддерживает наследование интерфейса, поэтому здесь не очень хороший ответ. В Dropbox такое случается не часто, и мы обычно решаем эту проблему, просто добавляя методы, специфичные для Android / iOS, в единый интерфейс и реализуя их с заглушками, которые выдают исключение на другой платформе. Мы обычно сталкиваемся с обратным случаем, где реализация была в Java / ObjC.

Если вам не нравится такой подход, и вам не нравится дублирование методов и множественное наследование, я думаю, что другой подход, который я бы порекомендовал, — это использование связанных подобъектов. Например. иметь интерфейс Foo с методом getAndroidStuff (), который возвращает интерфейс FooAndroid, содержащий только методы, специфичные для Android. Объект FooAndroid может внутренне удерживать ссылку на объект FooImpl, который обладает всеми функциями, и перенаправлять методы к нему.

Похоже, что более широкий вопрос здесь заключается в том, что на самом деле зависит от этих методов для платформы? Если реализация является кроссплатформенной, но требуется только на одной платформе, то не мешает просто использовать один класс C ++, а неиспользуемые методы не опасны. Если у вас есть платформо-зависимый код на C ++, то все становится немного неловко, так как это не было целью Djinni. Я думаю, что этот конкретный случай требует решения, отличного от общего случая наследования интерфейса.

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]