interface IFace : Object {
    public abstract void f ();
    public abstract void test ();
    public virtual void g () {
        stdout.printf("IFace.g ()\n");
    }
    public abstract int size { get; }
}

abstract class ACl : Object, IFace {
    public abstract void f ();
    public virtual void g () {
        stdout.printf("ACl.g ()\n");
    }
    public virtual void test () {
        this.f ();
    }
    public virtual int size {
        get {
            stdout.printf("ACl.size\n");
            return 0;
        }
    }
}

class BCl : ACl {
    public override void f () {
         stderr.printf ("BCl.f ()\n");
    }
}

class CCl : BCl, IFace {
    public override void f () {
       stderr.printf ("CCl.f ()\n");
    }
    public override void IFace.f () {
       if (GLib.unlikely (this.get_type () != typeof(CCl))) {
           stderr.printf ("CCl.Iface.f () [fake]\n");
           ((ACl)this).f ();
           return;
       }
       stderr.printf ("CCl.Iface.f ()\n");
    }
}

class DCl : CCl {
    public override void f () {
       stderr.printf ("DCl.f ()\n");
    }
    public override void g () {
       stdout.printf ("DCl.g ()\n");
    }
}


class CCl2 : BCl, IFace {
    public override void f () {
       stderr.printf ("CCl2.f ()\n");
    }
}

class DCl2 : CCl {
    public override void f () {
       stderr.printf ("DCl2.f ()\n");
    }
    public override void g () {
       stdout.printf ("DCl2.g ()\n");
    }
}
int main () {
    stderr.printf (">>> BCl\n");
    IFace b = new BCl ();
    b.f ();
    stderr.printf (">>\n");
    b.test ();
    stderr.printf (">>> CCl\n");
    IFace c = new CCl ();
    c.f ();
    stderr.printf (">>\n");
    c.test ();
    stderr.printf (">>> DCl\n");
    IFace d = new DCl ();
    d.f ();
    stderr.printf (">>\n");
    d.test ();
    stderr.printf (">>> CCl2\n");
    IFace c2 = new CCl2 ();
    c2.f ();
    stderr.printf (">>\n");
    c2.test ();
    stderr.printf (">>> DCl2\n");
    IFace d2 = new DCl ();
    d2.f ();
    stderr.printf (">>\n");
    d2.test ();
    b.test ();
    return 0;
}
