-
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
.