Массив объектов в джин
У меня есть 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
блок