
using GLib;

public class Test.Root: Object {
    int number;
    public int Number { get { return number; } }
    
    public Root(int number) {
        message("hello; number=%d", number);
        this.number = number;
    }
    
    public Root.clone(Root other) {
        this(other.Number);
        
        message("cloning other");
    }
}


public class Test.Derived: Test.Root {
    public Derived(int number)
    {
        base(number*2);
        message("hello, derived. Number=%d", number);   
    }               

    public Derived.clone(Derived other) {
        this(other.Number*2);
        
        message("cloning other, Derived");
    }
}

public class Test.Derived2OK: Test.Root {
    public Derived2OK(int number)
    {
        base(number*get_coef());
        message("hello, derived 2 OK. Number=%d", number);   
    }               
    
    private static int get_coef() {
        message("Derived2OK.get_coef() called");
        return 3;
    }

    public Derived2OK.clone(Derived2OK other) {
        this(other.Number*get_coef());
        
        message("cloning other, Derived 2 OK ");
    }

}

public class Test.Derived3Bad: Test.Root {
    public Derived3Bad(int number)
    {
        base(number*get_coef());
        message("hello, derived 3 Bad. Number=%d", number);   
    }               
    
    private /* NOT STATIC!!! */ int get_coef() {
        message("Derived3Bad.get_coef() called");
        return 4;
    }

    public Derived3Bad.clone(Derived3Bad other) {
        this(other.Number*get_coef());
        
        message("cloning other, Derived 3 Bad");
    }
}

public class Test.Derived4Worse: Test.Root {
    public Derived4Worse(int number, int coef)
    {    
        this.coef = coef; /* yes, this is a logic error but it should actually fail to compile */
        base(number*get_coef());
        message("hello, derived 4 Worse. Number=%d", number);   
        
    }               
    
    int coef;
    private /* cannot possibly be static !!! */ int get_coef() {
        message("Derived4Worse.get_coef() called");
        return coef;
    }

    public Derived4Worse.clone(Derived4Worse other) {
        this(other.Number*get_coef(), other.get_coef());
        
        message("cloning other, Derived 4 Worse");
    }
}


public class Test.Main: Object {

    private static int main (string[] args) {
        message("hello\n");
    
        Root r = new Root(4);                
        message("number #1 = %d\n", r.Number);
        Root d = new Root.clone(r);
        message("number #1b = %d\n", d.Number);
        
        r = new Derived(5);
        message("number #2 = %d\n", r.Number);
        d = new Derived.clone((Derived)r);
        message("number #2b = %d\n", d.Number);

        r = new Derived2OK(6);
        message("number #3 = %d\n", r.Number);
        d = new Derived2OK.clone((Derived2OK)r);
        message("number #3b = %d\n", d.Number);
        
        r = new Derived3Bad(7);
        message("number #4 = %d\n", r.Number);
        d = new Derived3Bad.clone((Derived3Bad)r);
        message("number #4b = %d\n", d.Number);
                
        r = new Derived4Worse(8,9);
        message("number #5 = %d\n", r.Number);
        d = new Derived4Worse.clone((Derived4Worse)r);
        message("number #5b = %d\n", d.Number);
                
        return 0;
    }
    
}
