Массив объектов в джин

У меня есть 2 класса: один с 2 свойствами и один с массивом. Я хочу сделать массив объектов первого класса.

Пример компилируется, но дает неправильный ответ. Зачем?


[indent=4]

class data

    prop first_name : string = " "
    prop last_name    : string = " "

class Arr : Object

    person : data
    dataset : array of data[]

    init
        person = new data()
        dataset = new array of data[3]

    def date_input() 

        print "\n data input \n"

        person.first_name = "Egon"
        person.last_name = "Meier"

        dataset[0] = person

        print dataset[0].first_name + " " + dataset[0].last_name

        person.first_name = "John"
        person.last_name = "Schneider"

        dataset[1] = person

        print dataset[1].first_name + " " + dataset[1].last_name

        person.first_name = "Erwin"
        person.last_name = "Müller"

        dataset[2] = person

        print dataset[2].first_name + " " + dataset[2].last_name


    def date_output()

        print "\n data output \n"

        for i : int = 0 to 2
            print dataset[i].first_name + " " + dataset[i].last_name

init

    Intl.setlocale()

    var a = new Arr()

    a.date_input()
    a.date_output()

1 ответ

Основная проблема в том, что вы обращаетесь к одному и тому же человеку три раза, но каждый раз меняете его имя. В Genie есть как типы значений, так и ссылочные типы. Типы значений проще и автоматически копируются при присваивании. Например:

[indent=4]
init
    a:int = 2
    b:int = a
    b = 3
    print( "a is still %i", a )

Тип ссылки имеет то преимущество, что его легко скопировать, Genie просто ведет подсчет сделанных ссылок. Таким образом, для копирования ссылочного типа счетчик ссылок увеличивается на единицу, но это означает, что изменения в базовом объекте будут влиять на все переменные, которые к нему относятся:

[indent=4]
init
    a:ReferenceTypeExample = new ReferenceTypeExample()
    a.field = 2
    b:ReferenceTypeExample = a
    b.field = 3
    print( "a.field is not 2, but %i", a.field )

class ReferenceTypeExample
    field:int = 0

В рабочем примере ниже я сделал Person объект значения с помощью readonly свойства:

[indent=4]
init
    Intl.setlocale()

    var group = new Group()
    print "\n data input \n"
    try
        group.add_person( new Person( "Egon", "Meier" ))
        group.add_person( new Person( "John", "Schneider" ))
        group.add_person( new Person( "Erwin", "Müller" ))
    except err:GroupError
        print( err.message )
    print( @"$group" )


class Person
    prop readonly first_name:string = ""
    prop readonly last_name:string = ""

    construct( first:string, last:string )
        _first_name = first
        _last_name = last


exception GroupError
    GROUP_FULL

class Group
    _people_count:int = -1
    _group:new array of Person
    _max_size:int = 2

    construct()
        _group = new array of Person[ _max_size ]

    def add_person( person:Person ) raises GroupError
        _people_count ++
        if _people_count > _max_size
            _people_count = _max_size
            raise new GroupError.GROUP_FULL(
                        "Group is full. Maximum is %i members",
                        _max_size + 1
                        )
        _group[ _people_count ] = person

        print( "  " + _group[ _people_count ].first_name +
               " " + _group[ _people_count ].last_name
             )

    def to_string():string
        result:string = "\n data output \n\n"
        if _people_count < 0
            result += "  empty group"
            return result
        for i:int = 0 to _people_count
            result += "  " + _group[i].first_name + \
                      " " + _group[i].last_name + "\n"
        return result

Некоторые подробности о коде:

  • Изменяя свойства, чтобы быть readonly при компиляции программы будет выдана ошибка, если она попытается изменить детали Person, В вашем примере, если вы измените свойства data быть readonly тогда компилятор Vala предупредит вас, что вы пытаетесь переписать текущий объект
  • Person в конструкторе установлены значения данных, и любая попытка изменить их является ошибкой
  • Для простого свойства Genie генерирует автоматическое вспомогательное поле, которое начинается с подчеркивания. Например в Person недвижимость first_name имеет вспомогательное поле _first_name и это то поле, которое установлено в конструкторе
  • Вместо включения имен людей в сам метод, метод называется add_person() используется, который занимает Person в качестве параметра. Это отделяет конкретные данные от абстрактного класса
  • Чеки были добавлены в add_person() метод, чтобы убедиться, что массив не выходит за его пределы. Если в группу добавлено больше людей, чем разрешено, возникает исключение
  • add_person() звонки в init блок создать Person как часть вызова метода. Это означает ссылку на Person объект не хранится в init блок
Другие вопросы по тегам