-
Invocation of overwritten method: Let
B be a subclass of A that overwrites the method m() declared in A as shown in the following code snippet:
class A {
public void m() {..}
}
class B extends A {
public void m() {..}
}
class C {
void foo(A someA) {
someA.m();
}
}
Invocation of m() on an object of type A in class C may actually call B's method m(). This is taken into account by introducing an indirect dependency from c to b.
- Assigning a method's return value: Consider the following example where again
B extends A:
class A {
public static B getSth() {...}
}
class B extends A {
}
class C {
void foo() {
A someA = A.getSth();
}
}
Removing B forces changes in A to make it error-free. If the return type of getSth() is changed to Object after the removal of B, foo() in C needs to be changed as Object can't be assigned to a variable of type A. Therefore c is indirectly dependent on b.
- Handing over a method's return value to another method: Let
A and B be as shown in (2.). Let class C invoke a method with a parameter of type A:
class C {
void foo() {
doSth(A.getSth());
}
static void doSth(A someA) {}
}
Similar to the previous example, changes on foo() would be required, if B was deleted and getSth()'s return type would have been changed to anything that is not of type A. Thus again c is indirectly dependent on b.
- Assigning a field: If in analogy to (2.) the class
C assigns a field of type B declared in A to another variable, C might have to be changed, if B was deleted:
class A {
static B someField;
}
class B extends A {
}
class C {
void foo() {
A someA = B.someField;
}
}
This leads again to an indirect dependency from c to b.
- Handing over a field to a method: If similar to (3.) the field declared in
A is handed over to a method, which requires a parameter of type A, changes in C might be necessary, if B was removed:
class C {
void foo() {
doSth(A.someField);
}
static void doSth(A someA) {}
}
Once again c is indirectly dependent on b.