Search code examples
variablesconstructorconstantsvala

Vala - Constant Initialization and Assignment in Object Constructor


I've been looking at the Vala programming language over the past few days, and it looks promising. However, I can't figure out how to properly assign a constant (currently the Vala equivalent to final) in object construction. For example, in Java:

import java.lang.Math;

public class Rectangle {
    public final double sideA;
    public final double sideB;
    public final double area;
    public final double diagonal;

    public Rectangle (double SideA, double SideB) {
        sideA = SideA;
        sideB = SideB;
        area = SideA * SideB;
        diagonal = Math.sqrt(Math.pow(SideA, 2) + Math.pow(SideB, 2));
    }
}

How would this be written in Vala?


Solution

  • Vala doesn't have a direct equivalent of Java's final keyword. I think the closest you are going to be able to come is something like this:

    public class Rectangle : GLib.Object {
      public double sideA { get; construct; }
      public double sideB { get; construct; }
      public double area { get; construct; }
      public double diagonal { get; construct; }
    
      public Rectangle (double SideA, double SideB) {
        GLib.Object (
          sideA: SideA,
          sideB: SideB,
          area: SideA * SideB,
          diagonal: Math.sqrt(Math.pow(SideA, 2) + Math.pow(SideB, 2)));
      }
    }
    

    construct properties are a bit different from final, largely because of how GObject construction works. They can only be set at construct time, but unlike final in Java (IIRC... most of my Java knowledge has been repressed) they can also be set during construct by a subclass. For example, this is perfectly acceptable:

    public class Square : Rectangle {
      public Square (double Side) {
        GLib.Object (
          sideA: Side,
          sideB: Side,
          area: Side * Side,
          diagonal: Math.sqrt(Math.pow(Side, 2) + Math.pow(Side, 2)));
      }
    }
    

    So, if you want to allow GObject-style construction (which I would suggest you do if you are making a library other people will call... if the code is just for you there is no need), you might want to do something more like this:

    public class Rectangle : GLib.Object {
      public double sideA { get; construct; }
      public double sideB { get; construct; }
    
      private double? _area = null;
      public double area {
        get {
          if ( _area == null )
            _area = sideA * sideB;
    
          return _area;
        }
      }
    
      private double? _diagonal = null;
      public double diagonal {
        get {
          if ( _diagonal == null )
            _diagonal = Math.sqrt(Math.pow(sideA, 2) + Math.pow(sideB, 2));
    
          return _diagonal;
        }
      }
    
      public Rectangle (double SideA, double SideB) {
        GLib.Object (
          sideA: SideA,
          sideB: SideB,
          area: SideA * SideB,
          diagonal: Math.sqrt(Math.pow(SideA, 2) + Math.pow(SideB, 2)));
      }
    }