精灵中的对象数组

时间:2017-02-09 12:15:03

标签: arrays genie

我有两个类:一个有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 个答案:

答案 0 :(得分:2)

根本问题是你指的是同一个人三次,但每次都改名。在Genie中,有值类型和引用类型。值类型更简单,并在分配时自动复制。例如:

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

参考类型的优点是可以轻松复制,Genie只需记录所做的参考。因此,要复制引用类型,引用计数会增加1,但这意味着对基础对象的更改将影响引用它的所有变量:

[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对象的引用