tech

[English] [Japanese]

13. accessor

This time, I will explain member accessors.

accessor

You can easily create accessors (get,set) for members.

For example:

// @lnsFront: ok
class Test {
   pri let val1:int;
   pri let mut val2:int {pub,pub};
   pri let val3:int {pub};
}
let mut test = new Test( 1, 2, 3 );
print( test.$val2, test.$val3 );  // 2 3
test.set_val2( 10 );
print( test.$val2, test.$val3 );  // 10 3

The definition of val2 in the above example is pri let val2:int {pub,pub};.

This {pub,pub} defines an accessor for val2. This specifies access control for getters, setters. This specification creates the following methods internally:

// @lnsFront: skip
pub fn Test.get_val2(): int {
   return self.val2;
}
pub fn Test.set_val2( val:int ) {
   self.val2 = val;
}

When accessing getters, use $ like this:

// @lnsFront: skip
let mut test = new Test( 1, 2, 3 );
print( test.$val2, test.$val3 );  // 2 3

test.$val2 is syntactic sugar for test.get_val2().

As above, accessor is declared in the order of "getter access control" and "setter access control".

If you don't need a setter, omit "setter access control".

If you don't need a getter but want a setter, declare it like this:

// @lnsFront: ok
class Test {
   pri let mut val1:int {non,pub};
}

This feature can be used, for example, to customize getters while automatically generating setters.

Accessors in LuneScript are ordinary methods. It's not something else like properties in C#.

getter return type

A getter's return type usually matches its member's type.

For example, the following getter for member list of Test returns a return value of type List<int> .

// @lnsFront: ok
class Test {
   pri let mut list:List<int> {pub};
}
let test = new Test( [] );
foreach val in test.$list { 
   print( val );
}

Here, the List<int> type is a mutable type, so external operations can change the value of the member list.

However, there are many situations in which we do not want to allow changes even if we allow access to external operations.

In such cases, you can control the return type of the getter. There are two ways to do this:

  • return as an immutable type
  • Return as a super class or interface type

return as an immutable type

You can create a getter that returns a mutable member as immutable by declaring the getter as follows:

// @lnsFront: ok
class Test {
   pri let mut list:List<int> {pub&};
}

This example calls it pub&. Appending & to the getter's "access control" makes its return type immutable.

Return as a super class or interface type

By declaring the getter as follows, you can return the type of the super class or interface instead of the member type itself.

// @lnsFront: ok
class Val {
}
class ValSub extend Val {
}

class Test {
   pri let val1:ValSub {pub};
   pri let val2:ValSub {pub:Val};
}
let test = new Test( new ValSub(), new ValSub() );
let val1 = test.$val1;
let val2 = test.$val2;

Here, the getter for Test.val1 is pub, but the getter for Test.val2 is pub:Val.

This causes test.$val1 to return type ValSub, but test.$val2 to return type Sub.

Customizing accessors

LuneScript accessors do not provide customization features (features that implement processing other than simple setters/getters) like C# properties.

This is because LuneScript's accessor is just a function to simplify method declarations, not a "different thing" like C#'s property. It's for

Note that you can use $ even if you define your own getter.

$val is syntactic sugar for get_val(), not exclusive to accessors.

summary

The LuneScript accessor has the following specifications.

  • Can be declared at the same time as member declaration
  • Declare getters first, then setters
  • Prepend a $ to the member name when accessing the getter.
  • An accessor is a convenience method definition, not a distinct concept from a method.

Next time we will discuss inheritance.