public class TestaaYliAli {                   // AW -05
   public static void main(String[] args) {

     // ohjelmoidaan tuttuun tapaan:

     Yli y = new Yli();
     System.out.println(y.getYlempi());
     y.setYlempi(35);
     System.out.println(y.getYlempi());

     // aliluokalla on yliluokan ominaisuudet:

     Ali a = new Ali();
     System.out.println(a.getYlempi());
     a.setYlempi(765);
     System.out.println(a.getYlempi());

     // ... ja aliluokan lisäämät ominaisuudet:

     System.out.println(a.getAlempi());
     a.setAlempi(9900);
     System.out.println(a.getAlempi());


     // aliluokan ilmentymä on myös yliluokan ilmentymä:

     Yli aa = new Ali();

     // ... mutta silloin käytössä ovat vain yliluokan ominaisuudet:

     System.out.println(aa.getYlempi());
     aa.setYlempi(19367);
     System.out.println(aa.getYlempi());

     // yritys aa.setAlempi(9876);
     // johtaisi virheeseen:

     // TestaaYliAli.java:31: cannot find symbol
     // symbol  : method setAlempi(int)
     // location: class Yli
     // aa.setAlempi(9876);
     //   ^


     // yliluokan ilmentymä ei ole aliluokan ilmentymä

     // yritys:

     // Ali yy = new Yli();

     // johtaa virheeseen:
     // TestaaYliAli.java:48: incompatible types
     // found   : Yli
     // required: Ali
     // Ali yy = new Yli();
     //          ^


     // onnistuisiko explisiittinen tyyppimuunnos?

     // Ali yy = (Ali)(new Yli());

     // Tämä kelpaakin kääntäjälle, mutta suoritus päättyy virheeseen:
     // Exception in thread "main" java.lang.ClassCastException: Yli
     //         at TestaaYliAli.main(TestaaYliAli.java:61)


     // Mutta jos Yli-tyyppinen muuttuja saa arvokseen Ali-tyyppisen olion, 
     // muunnos onnistuukin:

     Yli q = new Ali();
     Ali w = (Ali)q;

     // Vaikka q ja w osoittavat samaan olioon, vain w:tä käyttäen olioon on
     // mahdollista soveltaa aliluokassa määriteltyjä metodeita:

     w.setAlempi(4321);  // OK!
     // q.setAlempi(4321);  käännösvirhe
   }
}

