1

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

1 回答 1

2

根本问题是您三次提及同一个人,但每次都更改他们的名字。在 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. 在您的示例中,如果您将属性更改为datareadonly则 Vala 编译器将警告您正在尝试重写当前对象
  • Person在构造函数中设置了它的数据值,然后任何尝试更改它们都是错误的
  • 对于一个简单的属性,Genie 会生成一个以下划线开头的自动支持字段。例如,Person在属性first_name中具有支持字段_first_name,并且是在构造函数中设置的字段
  • 不是在方法本身中包含人名,而是add_person()使用一个以 aPerson作为参数的被调用方法。这将具体数据与抽象类分开
  • 检查已添加到add_person()方法中,以确保数组不会超出其限制。如果添加到组的人数超过允许的人数,则会引发异常
  • 块中的add_person()调用init创建Person作为方法调用的一部分。这意味着对Person对象的引用不会保存在init块中
于 2017-02-09T17:49:20.337 回答