2013-11-21 21:38:36 -08:00
|
|
|
^title Classes
|
|
|
|
|
|
2013-11-23 14:52:50 -08:00
|
|
|
Every value in Wren is an object, and every object is an instance of a class.
|
2015-09-01 08:16:04 -07:00
|
|
|
Even `true` and `false` are full-featured objects—instances of the
|
2015-11-08 13:31:22 -08:00
|
|
|
[Bool][] class.
|
|
|
|
|
|
|
|
|
|
[bool]: modules/core/bool.html
|
2013-11-23 14:52:50 -08:00
|
|
|
|
2015-11-07 11:09:04 -08:00
|
|
|
Classes define an objects *behavior* and *state*. Behavior is defined by
|
|
|
|
|
[*methods*][method calls] which live in the class. Every object of the same
|
|
|
|
|
class supports the same methods. State is defined in *fields*, whose values are
|
2015-01-03 23:27:02 -08:00
|
|
|
stored in each instance.
|
2013-12-28 09:37:41 -08:00
|
|
|
|
2015-11-07 11:09:04 -08:00
|
|
|
[method calls]: method-calls.html
|
|
|
|
|
|
2013-11-23 14:52:50 -08:00
|
|
|
## Defining a class
|
|
|
|
|
|
|
|
|
|
Classes are created using the `class` keyword, unsurprisingly:
|
|
|
|
|
|
2015-09-22 07:59:54 -07:00
|
|
|
:::wren
|
2013-11-23 14:52:50 -08:00
|
|
|
class Unicorn {}
|
|
|
|
|
|
|
|
|
|
This creates a class named `Unicorn` with no methods or fields.
|
|
|
|
|
|
2014-02-04 08:45:08 -08:00
|
|
|
## Methods
|
2013-12-28 09:37:41 -08:00
|
|
|
|
2014-10-15 06:36:42 -07:00
|
|
|
To let our unicorn do stuff, we need to give it methods.
|
2013-12-28 09:37:41 -08:00
|
|
|
|
2015-09-22 07:59:54 -07:00
|
|
|
:::wren
|
2013-12-28 09:37:41 -08:00
|
|
|
class Unicorn {
|
2015-09-01 08:16:04 -07:00
|
|
|
prance() {
|
2015-09-15 07:46:09 -07:00
|
|
|
System.print("The unicorn prances in a fancy manner!")
|
2013-12-28 09:37:41 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-07 11:09:04 -08:00
|
|
|
This defines a `prance()` method that takes no arguments. To add parameters, put
|
|
|
|
|
their names inside the parentheses:
|
2013-12-28 09:37:41 -08:00
|
|
|
|
2015-09-22 07:59:54 -07:00
|
|
|
:::wren
|
2014-01-30 06:51:52 -08:00
|
|
|
class Unicorn {
|
|
|
|
|
prance(where, when) {
|
2015-09-15 07:46:09 -07:00
|
|
|
System.print("The unicorn prances in " + where + " at " + when)
|
2014-01-30 06:51:52 -08:00
|
|
|
}
|
2013-12-28 09:37:41 -08:00
|
|
|
}
|
|
|
|
|
|
2015-11-07 11:09:04 -08:00
|
|
|
Since the number of parameters is part of a method's [signature][] a class can
|
|
|
|
|
define multiple methods with the same name:
|
2015-01-03 23:27:02 -08:00
|
|
|
|
2015-11-07 11:09:04 -08:00
|
|
|
[signature]: method-calls.html#signature
|
2013-12-28 09:37:41 -08:00
|
|
|
|
2015-09-22 07:59:54 -07:00
|
|
|
:::wren
|
2013-12-28 09:37:41 -08:00
|
|
|
class Unicorn {
|
2015-09-01 08:16:04 -07:00
|
|
|
prance() {
|
2015-09-15 07:46:09 -07:00
|
|
|
System.print("The unicorn prances in a fancy manner!")
|
2013-12-28 09:37:41 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
prance(where) {
|
2015-09-15 07:46:09 -07:00
|
|
|
System.print("The unicorn prances in " + where)
|
2013-12-28 09:37:41 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
prance(where, when) {
|
2015-09-15 07:46:09 -07:00
|
|
|
System.print("The unicorn prances in " + where + " at " + when)
|
2013-12-28 09:37:41 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-03 23:27:02 -08:00
|
|
|
It's often natural to have the same conceptual operation work with different
|
|
|
|
|
sets of arguments. In other languages, you'd define a single method for the
|
2015-11-07 11:09:04 -08:00
|
|
|
operation and have to check for missing optional arguments. In Wren, they are
|
|
|
|
|
different methods that you implement separately.
|
2015-09-01 08:16:04 -07:00
|
|
|
|
2015-11-07 11:09:04 -08:00
|
|
|
In addition to named methods with parameter lists, Wren has a bunch of other
|
|
|
|
|
different syntaxes for methods. Your classes can define all of them.
|
2015-09-01 08:16:04 -07:00
|
|
|
|
2015-11-07 11:09:04 -08:00
|
|
|
### Getters
|
2015-09-01 08:16:04 -07:00
|
|
|
|
2015-11-07 11:09:04 -08:00
|
|
|
A getter leaves off the parameter list and the parentheses:
|
2015-09-01 08:16:04 -07:00
|
|
|
|
2015-09-22 07:59:54 -07:00
|
|
|
:::wren
|
2015-09-01 08:16:04 -07:00
|
|
|
class Unicorn {
|
|
|
|
|
isFancy { true } // Unicorns are always fancy.
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-07 11:09:04 -08:00
|
|
|
### Setters
|
|
|
|
|
|
|
|
|
|
A setter has `=` after the name, followed by a single parenthesized parameter:
|
2015-02-26 23:08:36 -08:00
|
|
|
|
2015-09-22 07:59:54 -07:00
|
|
|
:::wren
|
2015-11-07 11:09:04 -08:00
|
|
|
class Unicorn {
|
|
|
|
|
rider=(value) {
|
|
|
|
|
System.print("I am being ridden by " + value)
|
|
|
|
|
}
|
2015-02-26 23:08:36 -08:00
|
|
|
}
|
|
|
|
|
|
2015-11-07 11:09:04 -08:00
|
|
|
### Operators
|
2015-02-26 23:08:36 -08:00
|
|
|
|
2015-11-07 11:09:04 -08:00
|
|
|
Prefix operators, like getters, have no parameter list:
|
2015-02-26 23:08:36 -08:00
|
|
|
|
2015-09-22 07:59:54 -07:00
|
|
|
:::wren
|
2015-11-07 11:09:04 -08:00
|
|
|
class Unicorn {
|
|
|
|
|
- {
|
|
|
|
|
System.print("Negating a unicorn is weird")
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-02-26 23:08:36 -08:00
|
|
|
|
2015-11-07 11:09:04 -08:00
|
|
|
Infix operators, like setters, have a single parenthesized parameter for the
|
|
|
|
|
right-hand operand:
|
2015-02-26 23:08:36 -08:00
|
|
|
|
2015-09-22 07:59:54 -07:00
|
|
|
:::wren
|
2015-11-07 11:09:04 -08:00
|
|
|
class Unicorn {
|
|
|
|
|
-(other) {
|
|
|
|
|
System.print("Subtracting " + other + " from a unicorn is weird")
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-01-03 23:27:02 -08:00
|
|
|
|
2015-11-07 11:09:04 -08:00
|
|
|
A subscript operator puts the parameters inside square brackets and can have
|
|
|
|
|
more than one:
|
2015-01-03 23:27:02 -08:00
|
|
|
|
2015-09-22 07:59:54 -07:00
|
|
|
:::wren
|
2015-01-03 23:27:02 -08:00
|
|
|
class Unicorn {
|
2015-11-07 11:09:04 -08:00
|
|
|
[index] {
|
|
|
|
|
System.print("Unicorns are not lists!")
|
2015-01-03 23:27:02 -08:00
|
|
|
}
|
|
|
|
|
|
2015-11-07 11:09:04 -08:00
|
|
|
[x, y] {
|
|
|
|
|
System.print("Unicorns are not matrices either!")
|
2015-01-03 23:27:02 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-07 11:09:04 -08:00
|
|
|
Unlike with named methods, you can't define a subscript operator with an empty
|
|
|
|
|
parameter list.
|
2015-01-03 23:27:02 -08:00
|
|
|
|
2015-11-07 11:09:04 -08:00
|
|
|
As the name implies, a subscript setter looks like a combination of a subscript
|
|
|
|
|
operator and a setter:
|
2015-01-03 23:27:02 -08:00
|
|
|
|
2015-11-07 11:09:04 -08:00
|
|
|
:::wren
|
|
|
|
|
class Unicorn {
|
|
|
|
|
[index]=(value) {
|
|
|
|
|
System.print("You can't stuff " + value + " into me at " + index)
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-01-03 23:27:02 -08:00
|
|
|
|
2015-11-07 11:09:04 -08:00
|
|
|
## This
|
2015-01-03 23:27:02 -08:00
|
|
|
|
2015-11-07 11:09:04 -08:00
|
|
|
**TODO: Integrate this into the page better.**
|
2015-01-03 23:27:02 -08:00
|
|
|
|
2015-11-07 11:09:04 -08:00
|
|
|
The special `this` keyword works sort of like a variable, but has special
|
|
|
|
|
behavior. It always refers to the instance whose method is currently being
|
|
|
|
|
executed. This lets you invoke methods on "yourself".
|
2015-01-03 23:27:02 -08:00
|
|
|
|
2015-11-07 11:09:04 -08:00
|
|
|
It's an error to refer to `this` outside of a method. However, it's perfectly
|
|
|
|
|
fine to use it inside a function contained in a method. When you do, `this`
|
|
|
|
|
still refers to the instance whose method is being called.
|
2015-01-03 23:27:02 -08:00
|
|
|
|
2015-11-07 11:09:04 -08:00
|
|
|
This is unlike Lua and JavaScript which can "forget" `this` when you create a
|
|
|
|
|
callback inside a method. Wren does what you want here and retains the
|
|
|
|
|
reference to the original object. (In technical terms, a function's closure
|
|
|
|
|
includes `this`.)
|
2013-12-28 09:37:41 -08:00
|
|
|
|
|
|
|
|
## Constructors
|
|
|
|
|
|
2015-11-07 11:09:04 -08:00
|
|
|
Unicorns can prance around now (as well as a bunch of weird operators that don't
|
|
|
|
|
make sense outside of these examples), but we don't actually *have* any unicorns
|
|
|
|
|
to do it. To create instances of a class, we need a *constructor*. You can
|
|
|
|
|
define one like so:
|
2014-02-04 08:45:08 -08:00
|
|
|
|
2015-09-22 07:59:54 -07:00
|
|
|
:::wren
|
2014-02-04 08:45:08 -08:00
|
|
|
class Unicorn {
|
2015-07-21 07:24:53 -07:00
|
|
|
construct new(name, color) {
|
2015-09-15 07:46:09 -07:00
|
|
|
System.print("My name is " + name + " and I am " + color + ".")
|
2014-02-04 08:45:08 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-01 08:16:04 -07:00
|
|
|
The `construct` keyword says we're defining a constructor, and `new` is its
|
2015-11-07 11:09:04 -08:00
|
|
|
name. In Wren, all constructors have names. The word "new" isn't special to
|
|
|
|
|
Wren, it's just a common constructor name.
|
2015-09-01 08:16:04 -07:00
|
|
|
|
2015-11-07 11:09:04 -08:00
|
|
|
To make a unicorn now, we call the constructor method on the class itself:
|
2015-09-01 08:16:04 -07:00
|
|
|
|
2015-09-22 07:59:54 -07:00
|
|
|
:::wren
|
2015-09-01 08:16:04 -07:00
|
|
|
var fred = Unicorn.new("Fred", "palomino")
|
|
|
|
|
|
|
|
|
|
Giving constructors names is handy because it means you can have more than one,
|
|
|
|
|
and each can clarify how it creates the instance:
|
2014-02-04 08:45:08 -08:00
|
|
|
|
2015-09-22 07:59:54 -07:00
|
|
|
:::wren
|
2014-02-04 08:45:08 -08:00
|
|
|
class Unicorn {
|
2015-07-21 07:24:53 -07:00
|
|
|
construct brown(name) {
|
2015-09-15 07:46:09 -07:00
|
|
|
System.print("My name is " + name + " and I am brown.")
|
2014-02-04 08:45:08 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-01 08:16:04 -07:00
|
|
|
var dave = Unicorn.brown("Dave")
|
|
|
|
|
|
|
|
|
|
Note that we have to declare a constructor because, unlike some other
|
|
|
|
|
languages, Wren doesn't give you a default one. This is useful because some
|
|
|
|
|
classes aren't designed to be constructed. If you have an abstract base class
|
|
|
|
|
that just contains methods to be inherited by other classes, it doesn't need
|
|
|
|
|
and won't have a constructor.
|
|
|
|
|
|
|
|
|
|
Like other methods, constructors can obviously have arguments, and can be
|
|
|
|
|
overloaded by [arity](#signature). A constructor *must* be a named method with
|
|
|
|
|
a (possibly empty) argument list. Operators, getters, and setters cannot be
|
|
|
|
|
constructors.
|
2015-07-10 09:18:22 -07:00
|
|
|
|
|
|
|
|
A constructor is actually a pair of methods. You get a method on the class:
|
2014-02-04 08:45:08 -08:00
|
|
|
|
2015-09-22 07:59:54 -07:00
|
|
|
:::wren
|
2015-09-01 08:16:04 -07:00
|
|
|
Unicorn.brown("Dave")
|
2015-07-10 09:18:22 -07:00
|
|
|
|
|
|
|
|
That creates the new instance, then it invokes the *initializer* on that
|
|
|
|
|
instance. This is where the constructor body you defined gets run.
|
2013-12-28 09:37:41 -08:00
|
|
|
|
2015-07-10 09:18:22 -07:00
|
|
|
This distinction is important because it means inside the body of the
|
|
|
|
|
constructor, you can access `this`, assign [fields](#fields), call superclass
|
|
|
|
|
constructors, etc.
|
2014-04-08 21:18:17 -07:00
|
|
|
|
2015-01-03 23:27:02 -08:00
|
|
|
## Fields
|
2014-04-08 21:18:17 -07:00
|
|
|
|
2015-01-03 23:27:02 -08:00
|
|
|
All state stored in instances is stored in *fields*. Each field has a named
|
|
|
|
|
that starts with an underscore.
|
2014-04-08 21:18:17 -07:00
|
|
|
|
2015-09-22 07:59:54 -07:00
|
|
|
:::wren
|
2015-01-03 23:27:02 -08:00
|
|
|
class Rectangle {
|
|
|
|
|
area { _width * _height }
|
2014-04-08 21:18:17 -07:00
|
|
|
|
2015-01-03 23:27:02 -08:00
|
|
|
// Other stuff...
|
2014-04-08 21:18:17 -07:00
|
|
|
}
|
|
|
|
|
|
2015-01-03 23:27:02 -08:00
|
|
|
Here, `_width` and `_height` in the `area` [getter](classes.html#methods) refer
|
|
|
|
|
to fields on the rectangle instance. You can think of them like `this.width`
|
|
|
|
|
and `this.height` in other languages.
|
2014-04-08 21:18:17 -07:00
|
|
|
|
2015-01-03 23:27:02 -08:00
|
|
|
When a field name appears, Wren looks for the nearest enclosing class and looks
|
|
|
|
|
up the field on the instance of that class. Field names cannot be used outside
|
|
|
|
|
of an instance method. They *can* be used inside a [function](functions.html)
|
|
|
|
|
in a method. Wren will look outside any nested functions until it finds an
|
|
|
|
|
enclosing method.
|
2014-04-08 21:18:17 -07:00
|
|
|
|
2015-01-03 23:27:02 -08:00
|
|
|
Unlike [variables](variables.html), fields are implicitly declared by simply
|
|
|
|
|
assigning to them. If you access a field before it has been initialized, its
|
|
|
|
|
value is `null`.
|
2014-04-08 21:18:17 -07:00
|
|
|
|
2015-01-03 23:27:02 -08:00
|
|
|
### Encapsulation
|
2014-04-08 21:18:17 -07:00
|
|
|
|
2015-03-27 06:46:12 -07:00
|
|
|
All fields are *private* in Wren—an object's fields can only be directly
|
|
|
|
|
accessed from within methods defined on the object's class. You cannot even
|
|
|
|
|
access fields on another instance of your own class, unlike C++ and Java.
|
2014-04-08 21:18:17 -07:00
|
|
|
|
2015-01-03 23:27:02 -08:00
|
|
|
If you want to make a property of an object visible, you need to define a
|
|
|
|
|
getter to expose it:
|
2014-04-08 21:18:17 -07:00
|
|
|
|
2015-09-22 07:59:54 -07:00
|
|
|
:::wren
|
2015-01-03 23:27:02 -08:00
|
|
|
class Rectangle {
|
|
|
|
|
width { _width }
|
|
|
|
|
height { _height }
|
2014-04-08 21:18:17 -07:00
|
|
|
|
2015-01-03 23:27:02 -08:00
|
|
|
// ...
|
|
|
|
|
}
|
2014-04-08 21:18:17 -07:00
|
|
|
|
2015-01-03 23:27:02 -08:00
|
|
|
To allow outside code to modify the field, you'll also need to provide setters:
|
2013-12-28 09:37:41 -08:00
|
|
|
|
2015-09-22 07:59:54 -07:00
|
|
|
:::wren
|
2015-01-03 23:27:02 -08:00
|
|
|
class Rectangle {
|
|
|
|
|
width=(value) { _width = value }
|
|
|
|
|
height=(value) { _height = value }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
One thing we've learned in the past forty years of software engineering is that
|
|
|
|
|
encapsulating state tends to make code easier to maintain, so Wren defaults to
|
|
|
|
|
keeping your object's state pretty tightly bundled up. Don't feel that you have
|
|
|
|
|
to or even should define getters or setters for most of your object's fields.
|
2013-12-28 09:37:41 -08:00
|
|
|
|
|
|
|
|
## Metaclasses and static members
|
|
|
|
|
|
|
|
|
|
**TODO**
|
2013-11-23 14:52:50 -08:00
|
|
|
|
2015-01-03 23:27:02 -08:00
|
|
|
### Static fields
|
|
|
|
|
|
|
|
|
|
A name that starts with *two* underscores is a *static* field. They work
|
|
|
|
|
similar to [fields](#fields) except the data is stored on the class itself, and
|
|
|
|
|
not the instance. They can be used in *both* instance and static methods.
|
|
|
|
|
|
2015-09-22 07:59:54 -07:00
|
|
|
:::wren
|
2015-02-28 11:26:18 -05:00
|
|
|
class Foo {
|
2015-03-01 08:39:53 -08:00
|
|
|
// Set the static field.
|
|
|
|
|
static set(a) {
|
|
|
|
|
__a = a
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
setFromInstance(a) {
|
|
|
|
|
__a = a
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Can use __a in both static methods...
|
|
|
|
|
static bar { __a }
|
|
|
|
|
|
|
|
|
|
// ...and instance ones.
|
|
|
|
|
baz { __a }
|
2015-02-28 11:26:18 -05:00
|
|
|
}
|
2015-01-03 23:27:02 -08:00
|
|
|
|
2015-03-01 08:39:53 -08:00
|
|
|
Just like instance fields, static fields are initially `null`:
|
|
|
|
|
|
2015-09-22 07:59:54 -07:00
|
|
|
:::wren
|
2015-10-18 15:56:52 -07:00
|
|
|
System.print(Foo.bar) //> null
|
2015-03-01 08:39:53 -08:00
|
|
|
|
|
|
|
|
They can be used from static methods:
|
|
|
|
|
|
2015-09-22 07:59:54 -07:00
|
|
|
:::wren
|
2015-02-28 11:26:18 -05:00
|
|
|
Foo.set("foo")
|
2015-10-18 15:56:52 -07:00
|
|
|
System.print(Foo.bar) //> foo
|
2015-03-01 08:39:53 -08:00
|
|
|
|
|
|
|
|
And also instance methods. When you do so, there is still only one static field
|
|
|
|
|
shared among all instances of the class:
|
|
|
|
|
|
2015-09-22 07:59:54 -07:00
|
|
|
:::wren
|
2015-07-10 09:18:22 -07:00
|
|
|
var foo1 = Foo.new()
|
|
|
|
|
var foo2 = Foo.new()
|
2015-03-01 08:39:53 -08:00
|
|
|
|
|
|
|
|
foo1.setFromInstance("updated")
|
2015-10-18 15:56:52 -07:00
|
|
|
System.print(foo2.baz) //> updated
|
2015-01-03 23:27:02 -08:00
|
|
|
|
2013-11-23 14:52:50 -08:00
|
|
|
## Inheritance
|
|
|
|
|
|
2015-01-03 23:27:02 -08:00
|
|
|
A class can inherit from a "parent" or *superclass*. When you invoke a method
|
|
|
|
|
on an object of some class, if it can't be found, it walks up the chain of
|
|
|
|
|
superclasses looking for it there.
|
2013-11-23 14:52:50 -08:00
|
|
|
|
2015-01-03 23:27:02 -08:00
|
|
|
By default, any new class inherits from `Object`, which is the superclass from
|
|
|
|
|
which all other classes ultimately descend. You can specify a different parent
|
|
|
|
|
class using `is` when you declare the class:
|
2013-11-23 14:52:50 -08:00
|
|
|
|
2015-09-22 07:59:54 -07:00
|
|
|
:::wren
|
2013-11-23 14:52:50 -08:00
|
|
|
class Pegasus is Unicorn {}
|
|
|
|
|
|
|
|
|
|
This declares a new class `Pegasus` that inherits from `Unicorn`.
|
|
|
|
|
|
2015-11-07 11:09:04 -08:00
|
|
|
Note that you should not create classes that inherit from the built-in types
|
|
|
|
|
(Bool, Num, String, Range, List). The built-in types expect their internal bit
|
|
|
|
|
representation to be very specific and get horribly confused when you invoke one
|
|
|
|
|
of the inherited built-in methods on the derived type.
|
2015-01-06 08:37:57 +00:00
|
|
|
|
2015-01-03 23:27:02 -08:00
|
|
|
The metaclass hierarchy does *not* parallel the regular class hierarchy. So, if
|
|
|
|
|
`Pegasus` inherits from `Unicorn`, `Pegasus`'s metaclass will not inherit from
|
|
|
|
|
`Unicorn`'s metaclass. In more prosaic terms, this means that static methods
|
|
|
|
|
are not inherited.
|
2013-12-28 09:37:41 -08:00
|
|
|
|
2015-09-22 07:59:54 -07:00
|
|
|
:::wren
|
2014-10-15 06:36:42 -07:00
|
|
|
class Unicorn {
|
|
|
|
|
// Unicorns cannot fly. :(
|
|
|
|
|
static canFly { false }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class Pegasus is Unicorn {}
|
|
|
|
|
|
2015-10-18 15:56:52 -07:00
|
|
|
Pegasus.canFly //! Static methods are not inherited.
|
2014-10-15 06:36:42 -07:00
|
|
|
|
2015-07-10 09:18:22 -07:00
|
|
|
This also means constructors are not inherited:
|
2013-12-28 09:37:41 -08:00
|
|
|
|
2015-09-22 07:59:54 -07:00
|
|
|
:::wren
|
2014-10-15 06:36:42 -07:00
|
|
|
class Unicorn {
|
2015-10-18 15:56:52 -07:00
|
|
|
construct new(name) {
|
2015-09-15 07:46:09 -07:00
|
|
|
System.print("My name is " + name + ".")
|
2014-10-15 06:36:42 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class Pegasus is Unicorn {}
|
|
|
|
|
|
2015-10-18 15:56:52 -07:00
|
|
|
Pegasus.new("Fred") //! Pegasus does not define new().
|
2015-07-10 09:18:22 -07:00
|
|
|
|
|
|
|
|
Each class gets to control how it may be constructed independently of its base
|
|
|
|
|
classes. However, constructor *initializers* are inherited since those are
|
|
|
|
|
instance methods on the new object.
|
|
|
|
|
|
|
|
|
|
This means you can do `super` calls inside a constructor:
|
|
|
|
|
|
2015-09-22 07:59:54 -07:00
|
|
|
:::wren
|
2015-07-10 09:18:22 -07:00
|
|
|
class Unicorn {
|
2015-10-18 15:56:52 -07:00
|
|
|
construct new(name) {
|
2015-09-15 07:46:09 -07:00
|
|
|
System.print("My name is " + name + ".")
|
2015-07-10 09:18:22 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class Pegasus is Unicorn {
|
2015-10-18 15:56:52 -07:00
|
|
|
construct new(name) {
|
2015-07-10 09:18:22 -07:00
|
|
|
super(name)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-18 15:56:52 -07:00
|
|
|
Pegasus.new("Fred") //> My name is Fred
|
2015-11-07 11:09:04 -08:00
|
|
|
|
|
|
|
|
## Super
|
|
|
|
|
|
|
|
|
|
**TODO: Integrate better into page. Should explain this before mentioning
|
|
|
|
|
super above.**
|
|
|
|
|
|
|
|
|
|
Sometimes you want to invoke a method on yourself, but only methods defined in
|
|
|
|
|
one of your [superclasses](classes.html#inheritance). You typically do this in
|
|
|
|
|
an overridden method when you want to access the original method being
|
|
|
|
|
overridden.
|
|
|
|
|
|
|
|
|
|
To do that, you can use the special `super` keyword as the receiver in a method
|
|
|
|
|
call:
|
|
|
|
|
|
|
|
|
|
:::wren
|
|
|
|
|
class Base {
|
|
|
|
|
method() {
|
|
|
|
|
System.print("base method")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class Derived is Base {
|
|
|
|
|
method() {
|
|
|
|
|
super.method() //> base method
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
You can also use `super` without a method name inside a constructor to invoke a
|
|
|
|
|
base class constructor:
|
|
|
|
|
|
|
|
|
|
:::wren
|
|
|
|
|
class Base {
|
|
|
|
|
construct new(arg) {
|
|
|
|
|
System.print("base got " + arg)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class Derived is Base {
|
|
|
|
|
construct new() {
|
|
|
|
|
super("value") //> base got value
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
<a class="right" href="concurrency.html">Concurrency →</a>
|
|
|
|
|
<a href="functions.html">← Functions</a>
|