Thursday, March 8, 2012

Covariant return type. Liskov Principle as a language feature

Given these classes in Java:

class Animal 
{
    protected int _generation = 0;

    public Animal() {
        this(1);
    }
    
    public Animal(int generation) {
        _generation = generation;
    }

    public Animal spawn() {
        System.out.println("From Animal Spawn");
        return new Animal(_generation+1);
    }
}


class Dog extends Animal 
{    
    public Dog() {
        this(1);
    }
    
    public Dog(int generation) {
        _generation = generation;        
    }
    

    @Override
    public Dog spawn() {
        System.out.println("From Dog Spawn");
        return new Dog(_generation + 1);
    }
}


And this usage:

Animal a = new Dog();  
Animal x = a.spawn();
 
 
Dog b = new Dog();
Dog y = b.spawn();  


Output:
From Dog Spawn
From Dog Spawn

Java allows the above code as it supports covariant type on overriding method, it supports Liskov substitution principle on overriding methods, it allows overriding methods to return different type, as long as that type is a derived type from the overridden method. If you change the return type of Dog's spawn to other type, say String, it will result to compiler error.


Prior to Java 1.5, covariant is not possible, overriding method have to return the exactly same return type of the overridden method. And users will be forced to cast things around:

Java 1.4 and below:
class Dog extends Animal 
{
    Animal spawn() {        
        return new Dog(_generation + 1);
    } 
}

And you have to use this in Java 1.4 and below:
Dog b = new Dog();
Dog y = (Dog) b.spawn(); // removing the cast will result to compilation error, type mismatch


Covariant is supported in C++ too:

#include <cstdio>

class Animal
{
    protected: int _generation = 0;

    public: Animal() : Animal(1) {  
    }

    public: Animal(int generation) {
        _generation = generation;
    }

    public: virtual Animal* spawn()
    {
        puts("Spawn From Animal");
        return new Animal(_generation + 1);
    }
};

class Dog : public Animal
{
    public: Dog() : Dog(1) {  
    }

    public: Dog(int generation) {
        _generation = generation;
    }

    public: virtual Dog* spawn()
    {
        puts("Spawn From Dog");
        return new Dog(_generation + 1);
    }
};

int main()
{
    Animal* a = new Dog();
    Animal* x = a->spawn();

    Dog* b = new Dog();
    Dog* y = b->spawn();

    return 0;
}


C# 4 has no support for covariant return type. It has no support for Liskov Substitution Principle when overriding methods.

public class Test 
{
    public static void Main(string[] args) 
    {
        Animal a = new Dog();  
        Animal x = a.Spawn();
 
 
        Dog b = new Dog();
        Dog y = b.Spawn();
    }

}


class Animal 
{
    
    protected int _generation = 0;

    public Animal() : this(1) 
    {    
    }
    
    public Animal(int generation) 
    {
        _generation = generation;
    }

    public virtual Animal Spawn() 
    {
        System.Console.WriteLine("From Animal Spawn");
        return new Animal(_generation + 1);
    }
}


class Dog : Animal 
{    
    
    public Dog() : this(1)
    {
    }
    
    public Dog(int generation) 
    {
        _generation = generation;        
    }
    

    // Compilation error: 'Dog.Spawn()': return type must be 'Animal' to match overridden member 'Animal.Spawn()'
    public override Dog Spawn() 
    {
        System.Console.WriteLine("From Dog Spawn");
        return new Dog(_generation + 1);
    }
}


To fix that in C# 4, you have to make the return type of the overriding method to exactly the same return type of overridden method

public class Test 
{
    public static void Main(string[] args) 
    {
        Animal a = new Dog();  
        Animal x = a.Spawn();
 
 
        Dog b = new Dog();
        Dog y = (Dog) b.Spawn();
    }

}


class Animal 
{
    
    protected int _generation = 0;

    public Animal()
    {
        _generation = 1;
    }
    
    public Animal(int generation) 
    {
        _generation = 1;
    }

    public virtual Animal Spawn() 
    {
        System.Console.WriteLine("From Animal Spawn");
        return new Animal(_generation + 1);
    }
}


class Dog : Animal 
{    
    
    public Dog()
    {
    }
    
    public Dog(int generation) 
    {
        _generation = generation;        
    }
    

    public override Animal Spawn() 
    {
        System.Console.WriteLine("From Dog Spawn");
        return new Dog(_generation + 1);
    }
}

Then when receiving the returned value from the overriding method, cast it to its derived type when necessary:

Dog b = new Dog();
Dog y = (Dog) b.Spawn(); // cast is needed, covariant is not yet supported in C# for overriding methods. Liskov substitution principle is not yet possible on overriding methods.

NOTE: a missing vtable usually means the first non-inline virtual member function has no definition

When you encounter this compilation error:

Michael-Buens-MacBook:CppProj Michael$ gcc b.cpp
Undefined symbols for architecture x86_64:
  "operator new(unsigned long)", referenced from:
      _main in ccbv8mjf.o
      Alpha::doStuff(char) in ccbv8mjf.o
      Beta::doStuff(char) in ccbv8mjf.o
  "vtable for __cxxabiv1::__class_type_info", referenced from:
      typeinfo for Alphain ccbv8mjf.o
  NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
  "vtable for __cxxabiv1::__si_class_type_info", referenced from:
      typeinfo for Betain ccbv8mjf.o
  NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status


You are holding it wrong, use g++ :-)

Michael-Buens-MacBook:CppProj Michael$ g++ b.cpp


b.cpp (Liskov principle):
#include <cstdio>

class Alpha
{
 public: virtual Alpha* doStuff(char c)
 {
  printf("From Alpha\n");
  return new Alpha();
 }
};

class Beta : public Alpha
{
 public: virtual Beta* doStuff(char c)
 {
  printf("From Beta\n");
  return new Beta();
 }
};

int main()
{

 Alpha* a = new Beta();
 Alpha* x = a->doStuff('x');
 
 Beta* b = new Beta();
 Beta* y = b->doStuff('x'); // no need to cast to Beta
 
 
 return 0;
}

Tuesday, March 6, 2012

Java has smarter foreach

Given this..

class Animal { 
}

class Dog extends Animal { 
}

class Cat extends Animal { 
}




..Java's compilation of for each is smarter than C#

So this would not compile in Java:

private static void testAnimal() {     
                                               
 Animal[] a = { new Dog(), new Cat() };                                            
                                                                                   
 for(Dog d : a) { // Type mismatch: cannot convert from element type Animal to Dog 
  System.out.println("Hey!");                                                    
 }                                                                                 
}                                                                                     

Whereas C# would happily compile the same construct:

static void testAnimal ()
{
 Animal[] a = { new Dog(), new Cat() };
 
 foreach(Dog d in a)
 {
  Console.WriteLine ("Hey!");
 }
}

But that relaxed foreach would bite you where it hurts the most, i.e. during runtime. The above construct will produce this output and error during runtime:


Hey!

Unhandled Exception: System.InvalidCastException: Cannot cast from source type to destination type.
  at ListInitializer.MainClass.testAnimal () [0x00017] in /Users/Michael/Projects/ListInitializer/ListInitializer/Main.cs:47 
  at ListInitializer.MainClass.Main (System.String[] args) [0x00000] in /Users/Michael/Projects/ListInitializer/ListInitializer/Main.cs:40 
[ERROR] FATAL UNHANDLED EXCEPTION: System.InvalidCastException: Cannot cast from source type to destination type.
  at ListInitializer.MainClass.testAnimal () [0x00017] in /Users/Michael/Projects/ListInitializer/ListInitializer/Main.cs:47 
  at ListInitializer.MainClass.Main (System.String[] args) [0x00000] in /Users/Michael/Projects/ListInitializer/ListInitializer/Main.cs:40 


Cat is not compatible with Dog.


Though if the intention is to really iterate all Dogs only, you can do so by using OfType extension method:


static void testAnimal ()
{
 Animal[] a = { new Dog(), new Cat() };
 
 foreach(Dog d in a.OfType<Dog>())
 {
  Console.WriteLine ("Hey!");
 }
}

As of the time of this writing, Java still doesn't support extension method, this is where C# clearly trumps Java


To approximate the same in Java, you have to use good collections library (e.g. Guava):

private static void testAnimal() {     
                                               
 Animal[] a = { new Dog(), new Cat() };                                            
                                                                                   
 for(Dog d : Iterables.filter(Arrays.asList(a), Dog.class)) { 
  System.out.println("Hey!");                                                    
 }  
}                     

Assigning integer to character is perfectly allowable in Java, C/C++

char c = 65; // Java, C/C++ would allow this. C# won't
System.out.println(c); // outputs A



need to typecast in C#
char c = (char) 65;
Console.WriteLine(c);

Saturday, March 3, 2012

Java reference type primitives gotcha

Java has a gotcha on its reference type primitives, any reference type primitives that has a value between -128 to 127 are cached, in order to save memory. When you compare any number that fall on that range, don't be surprised that reference types with same values points to the same memory location

private static void firstTestRef() {                                   
 System.out.println("First Test Ref\n");                            
                                                                    
 Integer a = 126;                                                   
 Integer b = 127;                                                   
                                                                    
 System.out.printf("Same reference b == a : %b\n", b == a);         
 System.out.printf("Same value b.equals(a) : %b\n\n", b.equals(a)); 
                                                                    
 ++a;                                                               
 System.out.printf("Same reference b == a : %b\n", b == a);         
 System.out.printf("Same value b.equals(a) : %b\n\n", b.equals(a)); 
}                                                                      

Output:
First Test Ref

Same reference b == a : false
Same value b.equals(a) : false

Same reference b == a : true
Same value b.equals(a) : true


See the output above? When you increment a, the runtime will check first if the value is in -127 to 128 range, if it is, it will find an existing object with same value, and reference that object instead


Now check the output of this one, values that are not in -128 to 127 range:

private static void secondTestRef() {                                  
 System.out.println("Second Test Ref\n");                       
                                                                    
 Integer a = 128;                                                   
 Integer b = 129;                                                   
 Integer c = a;                                                     
                                                                    
                                                                    
 System.out.printf("Same reference a == c : %b\n", a == c);         
 System.out.printf("Same value a.equals(c) : %b\n\n", a.equals(c)); 
                                                                    
 System.out.printf("Same reference b == a : %b\n", b == a);         
 System.out.printf("Same value b.equals(a) : %b\n\n", b.equals(a)); 
                                                                    
 ++a;                                                               
 System.out.printf("Same reference b == a : %b\n", b == a);         
 System.out.printf("Same value b.equals(a) : %b\n\n", b.equals(a)); 
                                                                    
 --a;                                                               
 System.out.printf("Same reference a == c : %b\n", a == c);         
 System.out.printf("Same value a.equals(c) : %b\n\n", a.equals(c)); 
}   


Output:

Second Test Ref

Same reference a == c : true
Same value a.equals(c) : true

Same reference b == a : false
Same value b.equals(a) : false

Same reference b == a : false
Same value b.equals(a) : true

Same reference a == c : false
Same value a.equals(c) : true

When you increment a, even it will have same value as b, their referenced memory location will not be the same. Even if you assign a its old value, a will be a new object already; so, even a has same value as c, it will not reference c

Tuesday, February 28, 2012

Static initialization block

Static Initialization Block


package com.anicehumble;


public class MainClass {

 public static void main(String[] args) {  
 
  System.out.println("Hello");
  Great.test();
  Great.test();
      
 }
}

package com.anicehumble;

public class Great {

 static 
 {
  System.out.println("One Time");
 }
 
 public static void test()
 {
  System.out.println("Test");
 }
 
}

Output:
Hello
One Time
Test
Test


Friday, February 24, 2012

When in Rome do as Romans do

So if you are accustomed to C# importing all classes from a namespace with using keyword:

using System.Collections.Generic;

Don't be tempted to do the same in Java:

import java.util.*;

Import classes explicitly:

import java.util.List;
import java.util.ArrayList;