#!/usr/bin/ruby

#
## Class inheritance
#

class Animal {
    method is_animal {
        return true;
    }
}

class Mammals < Animal {
    method legs_num {
        return 4;
    }

    method type {
        return 'mammal';
    }
}

class Primates < Mammals, Animal {
    method has_tail {
        return true;
    }
}

class Dog() < Mammals {
    method speak {
        return "Ham-Ham!";
    }
}

class Human < Primates {
    method speak {
        return "Hello!";
    }

    method legs_num {
        return 2;
    }

    method has_tail {
        return false;
    }
}

do {
    class Foo {
        method here {
            "in foo"
        }
    }

    class Bar < Foo {
        method here {
            self.SUPER::here
        }
    }

    var obj = Bar()
    assert_eq(obj.here, "in foo")
}

do {
    module inher {
        class Sup {}
    }

    class Der() < inher::Sup {}
    assert(Der.kind_of(inher::Sup))
}

do {
    class Foo { }
    class Super::Meta < Foo { }

    var Super::x = 42
    assert(Super::Meta.kind_of(Foo))

    module Super {
        assert_eq(x, 42)
        assert(Meta.kind_of(main::Foo))
    }
}

do {
    class Duck {
        method speak { self.noise }
        method noise { "Quack" }
    }

    class VikingDuck < Duck {
        method noise { "Kvack" }
    }

    assert_eq(VikingDuck().speak, "Kvack")
}

var dog = Dog();
say "Dog is a #{dog.type}, has #{dog.legs_num} legs and says '#{dog.speak}'";

var human = Human();
say "Human is a #{human.type}, has #{human.legs_num} legs and says '#{human.speak}'";

assert_eq(human.is_animal, true);
assert_eq(dog.is_animal, true);
assert_eq(human.has_tail, false);
assert_eq(human.legs_num, 2);
assert_eq(dog.legs_num, 4);
assert_eq(human.speak, 'Hello!');
