Objects

Types are essential units to defines GreyCat data structure. Types define aggregated typed fields into a named type, later instantiated as an Object. It is a very similar concept to Classes used in other Object Oriented programming languages.


Type definition

Here is an example of a type in Greycat:

type Country {
  name: String;
  phoneCode: int;
  location: geo;
}

type City {
  name: String;
  population: int?;
}

Objects

Let’s create luxembourg object, an instance of type Country:

fn main() {
    var luxembourg = Country {
        name: "Luxembourg",
        phoneCode: 352,
        location: geo::new(49.8153, 6.1296),
    };
    println(luxembourg);
    println(luxembourg.phoneCode);
}
greycat run
# {"_type":"project.Country","name":"Luxembourg","phoneCode":352,"location":{"_type":"core.geo","lat":49.815300005,"lng":6.129600001}}
# 352

Static attributes

type Country{  
    static unknown_country_name: String = "Unknown Country";  
    name: String;
    phoneCode: int;
    location: geo;
}

fn main() {
    println(Country::unknown_country_name);
}

Functions on types

type Country {
    name: String;
    location: geo;

    fn print() {
        println("Hello from ${this.name}, location is latitude: ${this.location.lat()}, longitude: ${this.location.lng()}");
    }
}
fn main() {
    var luxembourg = Country { name: "luxembourg", location: geo::new(49.815300005, 6.129600001) };
    luxembourg.print();
}
greycat run
# Hello from Luxembourg, location is latitude: 49.815300005, longitude: 6.129600001

Enum

Enums are list of values known at compile-time that cannot be extended dynamically. They are very useful tools when list of options are part of a domain definition. They can be used through the keyword enum and can have or not values.

enum DaysOfTheWeek{
    monday("Monday");
    tuesday("Tuesday");
    wednesday("Wednesday");
    thursday("Thursday");
    friday("Friday");
    saturday("Saturday");
    sunday("Sunday");
}
enum TransactionChannel{
    web(0);
    mobile(1);
    other(2);
}
fn main(){
    var day = DaysOfTheWeek::monday; // same accessor as the static :: 
}

Generic parameters

GreyCat support up to two generic parameters for classes, for instance the map native class from STD library is defined as follow:

native type Map<K,V>{
    native fn get(k: K): V;
}

The generic parameters can be specialized during instance creation such as:

var m = Map<String,float>::new();
m.get("my_key");

Inheritance with abstract types

GreyCat support a simplified model of inheritance using the keyword extends. The child inherits all attributes and functions from it’s parent

Beware that the parent needs to have the keyword abstract such as:

abstract type Animal {
    age: int;
    fn eat() {
        println("Animal is eating");
    }
}
type Dog extends Animal {
    breed: String;
}

fn main(){
    var dog = Dog {
        age: 10,
        breed: "Golden Retriever"
    };
    dog.eat();
}

Greycat does not allow the child to override the parents functions, you can however define abstract functions on the parent, be advised these will become required on all Children

abstract type Animal {
    abstract fn makeSound();
}
type Dog extends Animal {
    fn makeSound() {
        println("Woof");
    }
}

Composition

GreyCat supports type composition such as:

abstract type Job {
  salary: int;
}

type Programmer extends Job {}

type Person {
  job: Job;
}

fn main() {
  var programmer = Programmer {
    salary: 1000
  };
  var person = Person {
    job: programmer
  };
}

Helper functions on types

GreyCat offers functions on types, such as parseNumber:

fn main() {
    println(parseNumber("123")); // 123
    println(parseNumber("12.3")); // 12.3
}

and some type inspection with sameType:

use util; // for Assert

type T {
    a: int;
}

fn main() {

    Assert::isTrue(sameType(1, parseNumber("123")));
    Assert::isTrue(sameType(1 as float, parseNumber("123.45")));

    Assert::isTrue(sameType(12_time, 342_time));
    Assert::isTrue(sameType(12_geo, 342_geo));
    Assert::isTrue(sameType(T{a: 12}, T{a:1234343}));

    var a = nodeTime<String>::new();
    var b = nodeTime<float>::new();
    a.setAt(12_time, "12");
    b.setAt(13_time, 13.4);
    Assert::isTrue(sameType(a, b)); // true!
}