looking for a specific use case where both a subclass and a class within the same package needs to access a protected field or method...
Well to me, such a use case is rather general than specific, and it stems from my preferences to:
- Start with as strict access modifier as possible, resorting to weaker one(s) only later as deemed necessary.
- Have unit tests reside in the same package as tested code.
From above, I can start designing for my objects with default access modifiers (I would start with private
but that would complicate unit testing):
public class Example {
public static void main(String [] args) {
new UnitTest().testDoSomething(new Unit1(), new Unit2());
}
static class Unit1 {
void doSomething() {} // default access
}
static class Unit2 {
void doSomething() {} // default access
}
static class UnitTest {
void testDoSomething(Unit1 unit1, Unit2 unit2) {
unit1.doSomething();
unit2.doSomething();
}
}
}
Side note in above snippet, Unit1
, Unit2
and UnitTest
are nested within Example
for simplicity of presentation, but in a real project, I would likely have these classes in separate files (and UnitTest
even in a separate directory).
Then, when a necessity arises, I would weaken access control from default to protected
:
public class ExampleEvolved {
public static void main(String [] args) {
new UnitTest().testDoSomething(new Unit1(), new Unit2());
}
static class Unit1 {
protected void doSomething() {} // made protected
}
static class Unit2 {
protected void doSomething() {} // made protected
}
static class UnitTest {
// ---> no changes needed although UnitTest doesn't subclass
// ...and, hey, if I'd have to subclass... which one of Unit1, Unit2?
void testDoSomething(Unit1 unit1, Unit2 unit2) {
unit1.doSomething();
unit2.doSomething();
}
}
}
You see, I can keep unit test code in ExampleEvolved
unchanged due to protected methods being accessible from the same package, even though accessing object is not a sub-class.
Less changes needed => safer modification; after all I changed only access modifiers and I did not modify what methods Unit1.doSomething()
and Unit2.doSomething()
do, so it is only natural to expect unit test code to continue run without modifications.
Best Answer
@Override was originally not in the language. When the need was felt to add it, it was easier to use a generic mechanism (annotations) than to add a new keyword to the language. Adding a new keyword is always an incompatible change since it can break programs which use that words as an identifier.
In languages which add an override marker right from day one, it is quite often a keyword (examples are Kotlin and Scala), in Java it was a matter of staying backwards-compatible with older Java version which did not have any override marker.