Checker BadExtension   as of Julia version 2.5.0 (built on 4 Jul 2018)

belongs to group Basic

Identify possibly inconsistent class redefinitions or method overriding


Java classes can be extended and methods overridden. Sometimes, it is possible that methods are redefined in a way that seems an overriding but is actually the definition of another, distinct method. This is often cause of ambiguities and bugs. Moreover, fields in Java cannot be overridden and a subclass may add a synonym field of a superclass: the class ends up having two fields with the same name. This is often a source of ambiguities and might lead programmers to think that the field is actually overridden at all uses, while distinct synonym fields are used at different program points.

This checker finds ambiguities and bugs in the extension of classes, method overriding and fields redefinition.

Action: Check if a method redefinition should rather be an overriding. Check if a synonym field, already defined in a superclass, should be removed or renamed.

Examples


Consider the following class:

import sub.C;

public class Super implements Cloneable {
  public final int k = 13;

  public Super() {}

  public float myMethod(int a, float f) {
    return a + f + k;
  }

  public void anotherMethod(C par) {}
}

and its subclasses

public class Sub1 extends Super implements Cloneable {
  public Sub1() {}

  public float myMethod(int a, int f) {
    return a + f;
  }
}
public class Sub2 extends Super {
  public Sub2() {}

  public float mymethod(int a, float f) {
    return a + f;
  }
}
public class Sub3 extends Super {
  public final int k = 17;

  public Sub3() {}

  public void anotherMethod(C par) {}
}

Note that there are two classes named C (neither shown above): the one used in Sub3 stays in the same package as these classes; that used in Super stays inside package sub. This checker issues the following warnings:

Sub1.java:1: [BadExtension: RedundantImplementsWarning] interface java.lang.Cloneable is already implemented by Super
Sub2.java:4: [BadExtension: CaseOverrideWarning] Should you rather override myMethod here instead of defining mymethod?
Sub3.java: [BadExtension: FieldShadowedWarning] Field k shadows a synonym non-private field in Super
Sub3.java:6: [BadExtension: ParametersOverrideWarning] Sub3.anotherMethod(C):void was possibly meant to override Super.anotherMethod(sub.C):void but parameter types do not match

The first warning states that interface Cloneable is already implemented by Super, hence it is useless to implement it again in its subclass Sub1. The second warning suggests that Sub2.mymethod() should possibly be an overriding of Super.myMethod(), since they are almost identical, up to capitalisation. The third warns about field f, that is defined both in class Super and in its subclass Sub3; note that its occurrence inside Super.myMethod() refers to its definition inside Super, always, also in instances of Sub3. That is, fields are not overridden, which was instead what the programmer possibly expected in this example. The last warning states that Sub3.anotherMethod() has the same signature as Super.anotherMethod() but for the type of the parameter, which is called C in both methods, although these are two distinct C's. Also in this case, the programmer might have expected to have defined a redefinition of a method, not another method.

In this example, the programmer would probably rewrite the classes as follows:

import sub.C;

public class Super implements Cloneable {
  public final int k = 13;

  public Super() {}

  public float myMethod(int a, float f) {
    return a + f + k;
  }

  public void anotherMethod(C par) {}
}
public class Sub1 extends Super {
  public Sub1() {}

  public float myMethod(int a, int f) {
    return a + f;
  }
}
public class Sub2 extends Super {
  public Sub2() {}

  public float myMethod(int a, float f) {
    return a + f;
  }
}
public class Sub3 extends Super {
  public Sub3() {}

  public void anotherMethod(sub.C par) {}
}