Наследование интерфейса в Vala - несовместимо с базовым методом

Я пытаюсь реализовать Gtk.StyleProvider в Vala. «Базовый класс» (в C) выглядит так:

GtkIconFactory *        gtk_style_provider_get_icon_factory ()
GtkStyleProperties *    gtk_style_provider_get_style ()
gboolean                gtk_style_provider_get_style_property ()

и в ВАПИ:

[CCode (cheader_filename = "gtk/gtk.h")]
public interface StyleProvider {
    public abstract unowned Gtk.IconFactory get_icon_factory (Gtk.WidgetPath path);
    public abstract unowned Gtk.StyleProperties get_style (Gtk.WidgetPath path);
    public abstract bool get_style_property (Gtk.WidgetPath path, Gtk.StateFlags state, GLib.ParamSpec pspec, GLib.Value value);
}

Где первые два метода должны возвращать только NULL в соответствии с документацией для GtkStyleProvider.

Таким образом, я написал некоторые Валы так:

public class DerivedStyleProvider : Gtk.StyleProvider
{
    public Gtk.IconFactory? get_icon_factory (Gtk.WidgetPath path)
    {
        return null;
    }

    public Gtk.StyleProperties? get_style (Gtk.WidgetPath path)
    {
        return null;
    }

    bool get_style_property (Gtk.WidgetPath path,
                    Gtk.StateFlags state,
                    GLib.ParamSpec pspec,
                    out GLib.Value value)
    {
        return false; //TODO
    }
}

У меня проблема с первыми двумя способами. Если они у меня такие, как написано здесь (с ?), то я получаю следующую ошибку:

error: overriding method `DerivedStyleProvider.get_icon_factory' is incompatible 
with base method `Gtk.StyleProvider.get_icon_factory': Base method expected 
return type `Gtk.IconFactory', but `Gtk.IconFactory?' was provided.
    public Gtk.IconFactory? get_icon_factory (Gtk.WidgetPath path)
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Метод gtk_style_provider_get_style() тот же.

Если я удалю ?, я получу следующие две ошибки для каждого метода:

error: overriding method `DerivedsStyleProvider.get_icon_factory' 
is incompatible with base method `Gtk.StyleProvider.get_icon_factory': Base 
method expected return type `Gtk.IconFactory', but `Gtk.IconFactory' was provided.
        public Gtk.IconFactory get_icon_factory (Gtk.WidgetPath path)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/Preferences.vala:138.3-138.14: warning: `null' incompatible with 
return type `Gtk.IconFactory`
                return null;
                ^^^^^^^^^^^

Первая ошибка особенно мне кажется немного странной, так как результат "ошибка: ожидал ТИП, получил ТИП"!

Добавление unowned к первым двум методам по-прежнему приводит к аналогичным ошибкам.

Как мне реализовать интерфейс Gtk.StyleProvider в Vala?


person Inductiveload    schedule 21.12.2016    source источник
comment
Вы должны указать методы как public override Gtk... (обратите внимание на ключевое слово override). Также сигнатура метода должна точно совпадать, поэтому вы должны использовать unowned там, где родительский метод использует unowned, и вы не можете просто ввести nullable (?), где родительский метод не использует nullable...   -  person Jens Mühlenhoff    schedule 21.12.2016
comment
Даже добавление override и удаление значений, допускающих значение NULL, приводит к error: PreferencesStyleProvider.get_icon_factory: no suitable method found to override. И если я не могу вернуть null, как выполнить документированные требования?   -  person Inductiveload    schedule 21.12.2016
comment
Вы можете вернуть null, так как Gtk.IconFactory является типом класса, вы случайно не используете экспериментальный ненулевой режим? Файл VAPI в любом случае нуждается в исправлении, он должен иметь значение NULL в файле vapi.   -  person Jens Mühlenhoff    schedule 21.12.2016
comment
Также я только сейчас понял, что Gtk.StyleProvider - это не абстрактный класс, а интерфейс. Извините, для реализации интерфейсов override AFAIK не нужен.   -  person Jens Mühlenhoff    schedule 21.12.2016
comment
Я не вижу --enable-experimental-non-null в команде valac.   -  person Inductiveload    schedule 21.12.2016


Ответы (1)


Это компилируется без ошибок или предупреждений в моей системе (Vala 0.32.1):

public class DerivedStyleProvider : GLib.Object, Gtk.StyleProvider
{
    public unowned Gtk.IconFactory get_icon_factory (Gtk.WidgetPath path)
    {
        // Evil cast to work around buggy declaration in VAPI file
        return (Gtk.IconFactory) null;
    }

    public Gtk.StyleProperties get_style (Gtk.WidgetPath path)
    {
        // Evil cast to work around buggy declaration in VAPI file
        return (Gtk.StyleProperties) null;
    }

    bool get_style_property (Gtk.WidgetPath path,
                    Gtk.StateFlags state,
                    GLib.ParamSpec pspec,
                    out GLib.Value value)
    {
        // I just assigned something here to make the compiler happy, you should make sure to use a correct value
        value = Value (typeof (string));
        return false; //TODO
    }
}

Я сделал эти изменения:

  • Выведите из GLib.Object в дополнение к интерфейсу.
  • Используйте unowned в первом методе.
  • Удалите значение nullable из возвращаемых типов.
  • Вставьте null в фактические типы классов. (Что некрасиво, но проблема в файле vapi.)
  • Присвойте фиктивное значение параметру out, чтобы избежать предупреждения компиляции;)
person Jens Mühlenhoff    schedule 21.12.2016
comment
Похоже, я выбрал не тот класс для своего первого знакомства с интерфейсом Vala! - person Inductiveload; 21.12.2016
comment
Спасибо, теперь и у меня работает! Это ясно объясняет несколько концепций Валы! - person Inductiveload; 21.12.2016
comment
Не за что, для этого и существует SO, мы всегда рады помочь пользователям с хорошо описанными проблемами/вопросами :). - person Jens Mühlenhoff; 21.12.2016