【问题标题】:array of objects in genie精灵中的对象数组
【发布时间】:2017-02-09 12:15:03
【问题描述】:

我有 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()

【问题讨论】:

    标签: arrays genie


    【解决方案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
    

    在下面的工作示例中,我使用readonly 属性将Person 设为值对象:

    [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() 方法以确保数组不会超出其限制。如果添加到组的人数超过允许的人数,则会引发异常
    • init 块中的add_person() 调用创建Person 作为方法调用的一部分。这意味着对 Person 对象的引用不会保存在 init 块中

    【讨论】:

    • 感谢您的帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-26
    • 1970-01-01
    • 2014-05-13
    • 2023-03-15
    • 2017-09-14
    • 1970-01-01
    相关资源
    最近更新 更多