Objects

Our arsenal of available data types so far includes numbers, strings, Boolean values, null as well as arrays of values created from these types. Each data type comes with its own semantics (literal meaning), and available operations (expressed as operators but also as functions: len(), sort(), etc).

However, software applications often deal with more complex, structured data entities that have some kind of properties and allow certain kinds of operations to be performed on them. For example, consider a Student type of entity. This data type may carry a few properties (first and last name, hometown, year of graduation). In addition, the Student may support certain operations, such as: "enroll student in a course", "calculate student's grade average", etc.

We can use the object keyword in Yas to define our own custom data type, and then create objects that are instances of the data type that we define.

Defining an Object Type

An object type is also known as a class in other programming languages. To define a new object type, use the object keyword.

Let's define a Student type. Before we do so, let's agree on the following specification.

Every student:

  • has a first name and a last name,
  • has an expected graduation date,
  • may declare a major, and
  • may have a list of classes that they are currently enrolled in. This list may be empty.

We declare a Student object type to encapsulate this information:

object Student(firstName, lastName, graduationDate) {
    let major = null
    let classes = []
}

To create an instance of our new Student type, we use the type identifier as if it were a function that returns an object of the requested type, like so:

let studentA = Student("Alice", "Lidell", 2027)
let studentB = Student("Boris", "Smirnoff", 2027)

Properties, Methods and Constructors

The object declaration looks a lot like a function declaration, with a few differences. The parameters of the object type become required properties of the object.

The function block that follows the list of object type property parameters is called the constructor, and the type's required properties are specified as the constructor's parameters.

The constructor may:

  • define additional optional object properties on the object using the let keyword
  • define object methods (functions) using the def keyword
  • execute any additional initialization code that is required to configure the object instance

A method is a kind of a property that is also a function. The scope of the object methods' blocks includes all of the properties defined inside the constructor block, as well as other methods. It does not include any local variables defined in other methods. Unlike some other languages, there is no this or self keyword in Yas: inside methods, refer to the object's properties simply by their name. You may have to watch out for name collisions with local variables or parameters of methods.

We can access the object's properties and methods using a period .:

console

Our object type has required properties firstName, lastName, graduationDate (required properties must be passed as arguments to the constructor) and optional properties major and classes (which is an empty array by default). Then, we assign some new values to the properties .major and .classes, and then we use the .enroll() method to add more class enrollments for each student.

Accessing an object member property or method that has not been declared will result in an error.

console

Constructors are Just Functions

Note that because a constructor is essentially just a function, we don't have to assign object instances to variables. We can create anonymous objects on the fly, and use them anywhere that expressions can be used, such as store objects in an array or use them as arguments to functions. For example:

console

Alternative Constructor Syntax

Recall that when using the ask() function, we often provide a type specifier to the let statement in order to convert the string returned by ask() to a numeric value. It turns out that it is simply calling the number constructor with the string value returned by ask(). In the same manner, when you initialize any variable with a custom object type, you can provide the name of the type in the let statement, and then the arguments from the right-hand side will simply be passed to the appropriate constructor:

let number a = "98097"    # this is equivalent to calling `let a = number("98097")`

let Student x = ("Alice", "Lidell", 2027)    # same as calling `Student("Alice", ....)`
let Student y = ("Bob", "Smith", 2028)

Note that in this case the arguments to the constructor, if there are more than one, must be wrapped in parentheses; otherwise the interpreter could get confused, whether the comma means more arguments to the constructor, or separating two variable declarations.

That's All, Folks

For the more experienced programmers checking this out, Yas provides only limited object-oriented facilities, amounting pretty much to simple object structs, with methods automatically scoped and bound to instances. In particular, it comes without any support for:

  • subclasses
  • interfaces
  • mixins
  • static type polymorphism
  • virtual methods
  • runtime reflection
  • no this or self symbol

Yas does make sure that you pass exactly the specified number of required properties as constructor arguments, but has no way of checking or matching the argument types. The "type specifier" in a let statement is just syntactic sugar for calling the constructor; it doesn't bind any type to the variable itself.

Yas "native" packages (for example, the Geometry package) provide certain builtin object types written in JavaScript that do employ the more comprehensive object-oriented facilities of ES2015/2016, but none of that machinery is exposed or accessible from Yas itself. The Math package simply exports the JS Math object methods.

Back (090-using-math-module)
Forward (Table of Contents)