In OOP, a covariant return type of a method is one that can be replaced by a "specialized" type when the method is overridden in a subclass.
C# does not support return type covariance. Covariant return types have been (partially) allowed in the Java language since the release of JDK5.0, so the following example wouldn't compile on a previous release:
// Classes used as return types: class Person {
} class Guy extends Person { } // "Class Guy is more specific than class Person" // Classes demonstrating method overriding: class Department { public Person getPerson() { return new Person(); } } class DepartmentOfGuys extends Department { public Guy getPerson() { return new Guy(); } }
More specifically, covariant (wide to narrower) or contravariant (narrow to wider) return type refers to a situation where the return type of the overriding method is changed to a type related to (but different from) the return type of the original overridden method. The relationship between the two covariant return types is usually one which allows substitution of the one type with the other, following the Liskov substitution principle. This usually implies that the return types of the overriding methods will be subtypes of the return type of the overridden method. The above example specifically illustrates such a case. If substitution is not allowed, the return type is invariant and causes a compile error.
This might be very useful while overriding the clone method, because instead of returning an object, you can override the method clone to return a more specific type, preventing you from casting to your type.
The convariant type rule can also be applied to Exceptions in methods siganture, for instance the close method in AutoCloseable Interface throws Exception, and the close method in the Closable Interface throws a specialized exception: IOException. You can implement the interface AutoCloseable to throw the Exception of your needs. For example:
class ProcessException extends Exception{public ProcessException(String message) {super(message);}}class Processor implements AutoCloseable{@Override //Throws our Custom Exceptionpublic void close() throws ProcessException {System.out.println("Closing resources...");}public void initiateProcess() {System.out.println("start process...");}}class MainTest{//Finnally block automatically//called with your clos method and specific exceptionpublic static void main(String args[]){try(Processor p = new Processor()){p.initiateProcess();throw new ProcessException("You can catch in thetry-with-resources statement your specific exception");} catch(ProcessException e) {e.printStackTrace();}}}
To close our topic remember that Generics are not covariant, they are invariant, therefore, the following code will not compile:
class A{List<Object> test(){return Collections.emptyList();}}class B extends A{@Override List<String> test() {return super.test();}}
Comments
Post a Comment