Genie Vala Generics и Nullable Types

Простой вопрос: как в следующем универсальном классе как определить универсальный тип и содержащиеся в нем типы, чтобы их можно было обнулять? Следующее не будет компилироваться.

class Pair? of G1, G2: Object

    _first:G1?
    _second:G2?

    construct()

        _first = null
        _second = null

    def insert( first:G1, second:G2 )

        _first = first
        _second = second

    def insert_first( value:G1 )

        _first = value

    def insert_second( value:G2 )

        _second = value

    def second():G2

        return _second

Использование:

var pair = new Pair() of string, string
pair = null

2 ответа

Решение

Благодаря тому, как работают Vala Generics, универсальные параметры всегда обнуляются.

Пока вы не включите --enable-experimental-non-null Переменные класса также могут иметь значение null, поэтому ваш код упрощается до:

[indent=4]
class Pair of G1, G2: Object

    _first:G1
    _second:G2

    construct()

        _first = null
        _second = null

    def insert( first:G1, second:G2 )

        _first = first
        _second = second

    def insert_first( value:G1 )

        _first = value

    def insert_second( value:G2 )

        _second = value

    def second():G2

        return _second

init
    var pair = new Pair of string, string
    pair = null

когда --enable-experimental-non-null включен, вы должны быть явно указаны в типе переменной. Я не знаю, как написать это в Genie, я пробовал это, но компилятору это не нравится:

init
    pair: Pair? of string, string = new Pair of string, string
    pair = null

В Вале это не проблема

class Pair<G1,G2>: Object {
    private G1 first;
    private G2 second;

    public Pair () {
        first = null;
        second = null;
    }

    // ...
}

int main () {
    Pair<string, string>? pair = new Pair<string, string> ();
    pair = null;
    return 0;
}

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

[indent = 4]
class Pair of G1, G2: Object

    _first:G1?
    _second:G2?

    def insert( first:G1, second:G2 )
        _first = first
        _second = second

    def insert_first( value:G1 )
        _first = value

    def insert_second( value:G2 )
        _second = value

    def second():G2
        return _second

Если вы должны переназначить переменную, которая имеет экземпляр объекта, на ноль, то это будет:

[indent = 4]
init
    var pair = new Pair of string,string()
    pair = null

Компилятор Vala, однако, будет разыменовывать pair когда это выходит за рамки. Так что я не уверен, почему вы должны назначить ноль.

Использование null в идеале будет использоваться только при взаимодействии с библиотекой C, на мой взгляд. Доступ к нулю может привести к сбою (ошибка сегментации), если он не проверен должным образом. Например:

init
    a:int? = 1
    a = null
    var b = a + 1

Компилятор Vala имеет экспериментальный ненулевой режим, который выполняет некоторую проверку на наличие небезопасного кода. Если вы скомпилируете следующее с переключателем Vala --enable-experimental-non-null:

[indent = 4]
init
    var pair = new Pair of string,string()
    pair = null

вы получите ошибку:

error: Assignment: Cannot convert fromноль до Pair<string,string>'

Если вы понимаете последствия, вы можете сказать компилятору, что все в порядке с:

[indent = 4]
init
    pair:Pair? = new Pair of string,string()
    pair = null
Другие вопросы по тегам