Static properties and methods on interfaces
In both Gosu and Java, you can add static variables to types to declare data that exists at the type level. For Gosu
classes, you add such data to a class by adding a declaration line with the static modifier:
public static var MyVariableAdding a var declaration does not imply the ability to get or set a variable or
property on an instance of the type. A var declaration on an interface
defines a static constant variable on the type. A static constant variable is conceptually
similar to a static variable in a Gosu class. However, for a variable on an interface, the
static keyword is implicit and the value is read-only. The declaration does
not specify the ability to get or set a variable or property on an instance of this type.
Although you can use property getter and setter syntax to define data used with object
instances, you do not use this syntax for static constant variables. This is why static
constant variables do not require assignment compatibility between the interface and other
types.
For example, the declaration of the Age variable in the following example
will not compile because it implicitly creates a static constant variable, which must be
initialized:
package examples.pl.gosu.intf
interface DemoInterface {
property get Name() : String
property set Name(n : String)
public function count(s : String) : int
public var Age : Integer // Compilation error. A static constant variable requires initialization.
}
Initializing the value of the static constant variable clears the error:
package examples.pl.gosu.intf
interface DemoInterface {
property get Name() : String
property set Name(n : String)
public function count(s : String) : int
public var Age : Integer = 18 // OK because the static constant variable is initialized.
}
The following code defines a class that implements the DemoInterface
interface:
uses examples.pl.gosu.intf.DemoInterface
class MyClass implements DemoInterface {
var _name : String
override property get Name() : String {
return "name: " + _name
}
override property set Name(n:String) {
_name = n
}
override function count(s : String) : int {
return s.length()
}
}
The following code creates an instance of the class and tests its properties:
var myObject = new MyClass()
myObject.Name = "Andy Applegate"
print(myObject.Name)
print(myObject.count(myObject.Name))
print(myObject.Age)
Output:
name: Andy Applegate
20
18
static modifier in the declaration of the age variable, but in
interface declarations this modifier is implicit and therefore redundant.To call a static interface method, do so using the interface name directly, rather than the name of the implementing class. This is required because static interface methods are not inherited.
package examples.pl.gosu.intf
interface DemoInterface {
property get Name() : String
property set Name(n : String)
public function count(s : String) : int
public var Age : Integer = 18
static function nameWithLabel( person: String ) : String {
return "Person: " + person
}
}
The following code defines a class that implements the modified
DemoInterface interface:
uses examples.pl.gosu.intf.DemoInterface
class MyClass implements DemoInterface {
var _name : String
override property get Name() : String {
return "name: " + _name
}
override property set Name(n:String) {
_name = n
}
override function count(s : String) : int {
return s.length()
}
}
The following code creates and tests an instance of the class, calling the
DemoInterface.nameWithLabel static interface method:
var myObject = new MyClass()
myObject.Name = "Andy Applegate"
print(myObject.Name)
// print(MyClass.nameWithLabel(myObject.Name)) // error: must use method directly on interface
print(DemoInterface.nameWithLabel( myObject.Name )) // OK
Output:
name: Andy Applegate
Person: name: Andy Applegate
Another reason static interface methods must be called directly from their interfaces is to
prevent conflicts when a class implements multiple interfaces having the same static method
names. In this example, a second interface, DemoInterface2, has an
identically named static method to the one in DemoInterface:
interface DemoInterface2 {
static function nameWithLabel( person: String ) : String {
return "Person2: " + person
}
}
MyClass is modified here to implement both interfaces:
class MyClass implements DemoInterface, DemoInterface2 {
var _name : String
override property get Name() : String {
return "name: " + _name
}
override property set Name(n:String) {
_name = n
}
override function count(s : String) : int {
return s.length()
}
}
The following code creates an instance of MyClass, calling the static
methods defined on both interfaces:
var myObject = new MyClass()
myObject.Name = "Andy Applegate"
print(myObject.Name)
print(DemoInterface.nameWithLabel( myObject.Name )) // ok
print(DemoInterface2.nameWithLabel( myObject.Name )) // ok
Output:
name: Andy Applegate
Person: name: Andy Applegate
Person2: name: Andy Applegate
In this last example, both interfaces can be implemented without conflict because their static methods are not inherited.
