Classes and Objects

From Plasmaworks

Jump to: navigation, search

The code examples are given for command-line Slag programs. To test the following examples in Plasmacore, type "gogo build" in a new project, set it up with project name "Test" and then edit src/test.slag and insert the given example, changing "class Test" to be "class Test : Screen".

Contents

Using a Class in Another File

When you start to have large files of code it's easier to segment them into different .slag files. When a programmer starts to do this they'll still want access to their code in other sections of their program.

To access the contents of another slag file just add:

"[include <filename>]"

You will, of course, remove the parenthesis in your code. Following that you will also replace "<filename>" with your actual .slag file name.

Basics

Name Example

 class Test
   METHODS
     method init
       local Name abe("Abe","Pralle")
       local var ty = Name("Ty","Heath")
 
       println( "$ and $ incorporated Plasmaworks" (abe.first,ty.first) )
         # Prints:
         #   Abe and Ty incorporated Plasmaworks
 
       println( //My name is $ - that's "$" on the roster.// (abe,abe.roster_form) )
         # Prints:
         #   My name is Abe Pralle - that's "Pralle, Abe" on the roster.
 endClass
 
 class Name( String first, String last )
   METHODS
     method to_String.String
       return "$ $" (first,last)
 
     method roster_form.String
       return "$, $" (last,first)
 endClass

Name Analysis

 class Test
  • Any number of classes may be defined per file. By default an object of the topmost class is created and its init() method is called as the program starting point.
   METHODS
  • Classes are defined by section, with the two primary sections being METHODS and PROPERTIES (aka instance variables or object variables). Other sections include CLASS_METHODS and CLASS_PROPERTIES (for static class members).
     method init
  • Slag's "initializers" are the constructors" of other languages. They are named "init".
  • By default a program starts at the init() method of the top class definition in a file.
       local Name abe("Abe","Pralle")
       local var ty = Name("Ty","Heath")
  • Local variables must be preceded by the keyword "local".
  • The syntax "local Name abe(...)" is shorthand for "local Name abe = Name(...)".
  • Writing the class name followed by an parenthesized argument list will create a new object. The new keyword is not used as it is in other languages.
  • "local var ty = Name(...)" is shorthand for "local Name ty = Name(...)". "var" is just a placeholder for whatever type the compiler determines is on the right-hand side of the assignment.
  • No semicolons are required.
       println( "$ and $ incorporated Plasmaworks" (abe.first,ty.first) )
  • Writing "$+$=$"(a,b,a+b) is the shorthand equivalent of writing a + "+" + b + "=" + (a+b). Formatted strings use the syntax: "string" (args). Any dollar signs in the string are format markers that are replaced by the to_String() versions of arguments in the following argument list. This is a compile-time replacement.
  • Properties (instance variables) may generally be directly accessed ("abe.first"). The concepts of public and private do not matter much in Slag; one of the primary reasons for using them does not apply (more on that later).
       println( //My name is $ - that's "$" on the roster.// (abe,abe.roster_form) )
  • Writing //string// is an alternate way to specify a literal string.
  • Methods do not need parentheses if there are no arguments.
 endClass
  • Slag's keywords are verbose camelCase: class/endClass, while/endWhile, if/elseIf/else/endIf, etcetera.
 class Name( String first, String last )
  • Writing "Name( String first, String last )" is shorthand for:
 class Name
   PROPERTIES
     first, last : String
 
   METHODS
     method init( String f, String l )
       first = f
       last = l
     ...
 endClass


   METHODS
     method to_String.String
       return "$ $" (first,last)
 
     method roster_form.String
       return "$, $" (last,first)
 endClass
  • Methods are declared in the form "method name(Type1 param1, Type2 param22, ...).ReturnType". The parentheses may be left off if there are no arguments. The ".ReturnType" is left off if there is no return type.
  • A trailing ":" is allowed on the method declaration (e.g. "to_String.String:"; writing it allows the body to be written on the same line if you so desire.
  • When a method name incorporates a specific data type, that data type is capitalized as it was originally written.

Methods as Properties

Distance Example

  class Test
    METHODS
      method init
        local Distance ruler()
        ruler.inches = 12
        println( "A ruler is $(.2) inches or $(.2) cm." (ruler.inches,ruler.cm) )
  
        local Distance kilometer()
        kilometer.km = 1
        println( "A kilometer is $ meters and $ miles." (kilometer.m,kilometer.miles) )
  endClass
  
  class Distance()
    PROPERTIES
      m : Real64
        # Distance is stored in meters and converted to all other
        # unit systems on the fly.
  
    METHODS
      method cm( Real64 n ):     m = n / 100
      method km( Real64 n ):     m = n * 1000
      method inches( Real64 n ): cm = n * 2.54
      method feet( Real64 n ):   inches = n * 12
      method miles( Real64 n ):  feet = n * 5280
  
      method cm.Real64:     return m * 100
      method km.Real64:     return m / 1000
      method inches.Real64: return cm / 2.54
      method feet.Real64:   return inches / 12
      method miles.Real64:  return feet / 5280
  endClass

Distance Analysis

  • Primitives are named Real64, Real32, Int64, Int32, Char, Byte, and Logical. The first five are equivalent to types double, float, long, int, and char in Java. "Byte" is equivalent to "unsigned char" in C++. "Logical" may be used as a Java "boolean", but Logical is a ternary type that supports literal values true, false, and void.
  • The string format "$(.2)" causes a real number to be displayed with exactly 2 digits after the decimal point.
  • Writing "obj.x = 5.0" is shorthand for "obj.x(5.0)" if an x(Real64) method exists. Such a method is called a property-set method.
  • Writing "y = obj.x" is shorthand for "y = obj.x()" if an x().Real64 method exists (the "Real64" could be any return type). Such a method is called a property-get method.
  • Do not be concerned as to whether "obj.x" is accessing a property or calling a method. Think of x as just a property in either case.
  • In short you can write methods that act like variables.

Transparent Access Methods

  • If you define property access methods, they will be called when you read or write a property.
  • These access methods are transparent - outside of a class you do not know or need to know whether the variable is being directly accessed or whether its going through a property-set or property-get method.
  • For a property "x : Real64", the property-get method that just returns the value of x would be "method x.Real64: return &x".
  • For "x : Real64", the property-set method that takes a new value and just set the property would be: "method x( Real64 new_x ): &x = new_x". There is a shorthand as well: "method x(x):".
  • An ampersand (&) bypasses access methods to allow direct property access.

Treasure Chest Example

 class Test
   METHODS
     method init
       local TreasureChest chest(5000)
       println( chest.gold )  # prints -1 since the chest is closed
       chest.open
       println( chest.gold )  # prints 1000, the max amount
 endClass
 
 class TreasureChest( Int32 gold )
   PROPERTIES
     is_open : Logical
 
   METHODS
     method open:  is_open = true
     method close: is_open = false
 
     method gold.Int32
       # Returns -1 if the chest is closed.
 
       if (not is_open) 
         # All logical operators are spelled out in word form: 
         # and, or, xor, not.
         return -1
       endIf
 
       # Use ampersand (&) to bypass any transparent access 
       # methods and directly access a property.
       return &gold  
 
     method gold( Int32 new_amount )
       # 1000 gold pieces is the max
       if (new_amount > 1000) new_amount = 1000
       &gold = new_amount
 
 endClass

Operator Methods

  • Almost all arithmetic and bitwise operators may be made to work with objects of a given class by defining operator methods for that class.
  • The binary operator methods that may be defined are: + - * / ^ & |, of the form "method op+(SomeType rhs).SomeType".
  • The unary operator methods that may be defined are: - !, of the form "op-.SomeType".
  • The assignment operator cannot be defined in this way.
  • Neither += nor ++ (etc.) may be defined in this way as underneath they are not distinct operators. "x++" is shorthand for "x = x + 1" and "x += y" is shorthand for "x = x + y".

Time Example

 class Test
   METHODS
     method init
       local Time now("10:58")
       local Time interval("2:03")
       local Time one("1:00")
       println( "The time is $." (now) )
       println( "$ after $ is $." (interval,now,now+interval) )
       println( "$ before $ is $." (interval,one,one-interval) )
 
       # Prints:
       #   The time is 10:58.
       #   2:03 after 10:58 is 1:01.
       #   2:03 before 1:00 is 11:57.
 endClass
 
 class Time( Int32 hours, Int32 minutes )
   METHODS
     method init( String time )
       local var values = time.split(':')
       hours = values[0].to_Int32
       minutes = values[1].to_Int32
 
     method to_String.String
       return "$:$(02)" (hours,minutes)
 
     method op+( Time other ).Time
       local Time result(hours,minutes)
       result.hours += other.hours
       result.minutes += other.minutes
       return result
 
     method op-( Time other ).Time
       local Time result(hours,minutes)
       result.hours -= other.hours
       result.minutes -= other.minutes
       return result
 
     method minutes(minutes)
       # Transparent property-set for 'minutes'.
       hours += minutes / 60
       &minutes %= 60
 
     method hours(hours)
       # Transparent property-set for 'hours'.
       &hours = hours.wrapped(1,12)
 endClass