OVERVIEW
FEATURE SUMMARY:
This change allow to delegate methods, interfaces and classes.
MAJOR ADVANTAGE:
It would be a first step for programmers to have something instead of inheritance, allowing to write better code.
MAJOR BENEFITS:
Java looks incomplete without something so base as delegating. Others are:
- Code more immune for changes(if interface changes, there will be not so much to change, or I would say, changes will be on the right place, but not on all projects)
- Decreasing costs of code modification.
- Explicit defining MethodModifiers
MAJOR DISADVANTAGE:
Changes cost.
ALTERNATIVES:
It's nothing that cannot be implemented in a simple way, but this change does not increase delegation complex, unreadablity, and costs of support with each method.
EXAMPLES
SIMPLE EXAMPLE:
InterfaceA ia = ...;
public delegate InterfaceA{
return ia;
}
}
ADVANCED EXAMPLE:
ClassSome cs = ... ; // ClassSome implements InterfaceA, InterfaceB, InterfaceC
Some some = ... ; // have the same methods from InterfaceA and InterfaceC but do not implements them
public delegate ClassSome exclude Object,InterfaceB{
if (cs==null) return some;
return cs;
}
}
DETAILS
SPECIFICATION:
DelegationDeclaration:
DelegationHeader DelegationBody
DelegationHeader:
DelegationModifiersopt delegate MethodSets Excludeopt Throwsopt DelegationDeclarator
DelegationModifiers:
DelegationModifier
DelegationModifiers DelegationModifier
DelegationModifier: one of
Annotation public protected private abstract static final synchronized
Exclude:
exclude MethodSets
MethodSets:
MethodSet
MethodSets, MethodSet
MethodSet: one of
ClassOrInterfaceType InterfaceMemberDeclaration
DelegationBody:
same with: MethodBody except ReturnStatement
ReturnStatement:
return* Expression
return work in different way in delegation than in method.
For each method with ResultType(Type) it's interpreted:
return (Expression).MethodIdentifier(ActualParameters);
For each method with ResultType(void) it's interpreted:
(Expression).MethodIdentifier(ActualParameters);
return;
COMPILATION:
Delegation is deployed to all methods that occur in 'delegate MethodSets' and do not occur in Excludeopt.
All methods have modifiers: DelegationModifiersopt
Declared exception in Throwsopt are added to each method ExceptionTypeList.
TESTING:
Normal way.
LIBRARY SUPPORT:
No
REFLECTIVE APIS:
No changed.
OTHER CHANGES:
None.
MIGRATION:
No need.
COMPATIBILITY
All working programs will still work. New byte code is compatible with old one.
REFERENCES
Instrukcje
Opinia aby zabronić 'złego' dziedziczenia jest dość powszechnie znana. Jednak żeby być szczerym trzeba stwierdzić, że nie ma w języku mechanizmu który by wspierał choćby delegacje. W związku z oczywistymi utrudnieniami pojawiają się choćby głosy, ażeby wprowadzić do języka properties (czyt. automatycznie dodawanie get-erów i set-erów). O ile pomysł ten jest ciut poroniony np.: jeśli chcieli byśmy oddzielnie zdefiniować min. widoczność to musieli byśmy napisać praktycznie tyle samo kodu ile przy zwykłej metodzie. Jednak sam problem ma swoje podstawy.
Przyjrzyjmy się więc przykładowej konstrukcji która miała by pozwolić na delegowanie class i interfejsów. Oraz możliwościom jakie by ona dała.
Przegląd
Główne zalety / korzyści:
- Ujednolicenie sposobu delegacji wielu metod.
- Łatwy refactor (zakomentowanie delegacji, wykluczenie metody).
- Możliwość jawnego zdefiniowania widoczności jak i innych modyfikatorów (static / final)
Najistotniejsze wady:
- Koszt zmian.
- Zdefiniować reagowanie na ewentualny null.
Inne rozwiązania:
- Pisać wszystko ręcznie.
- Rozszerzyć środowisko o lepsze generatory kodu.
Podsumowanie:
Przykłady:
Baza
String getName();
ArrayList<Date> getDates();
}
public InterfaceA info();
}
public int delta = 0;
abstract public void printState();
}
Przykład
private static InterfaceA interfaceA;
public static delegate InterfaceA from interfaceA onnull {throw new NullPointerException(InterfaceA.class.getSimpleName());};
}
Wyglądał by po skompilowaniu jak:
private static InterfaceA interfaceA;
public static String getName() {
if (interfaceA == null) throw new NullPointerException(InterfaceA.class.getSimpleName());
return interfaceA.getName();
}
public static ArrayList<Date> getDates() {
if (interfaceA == null) throw new NullPointerException(InterfaceA.class.getSimpleName());
return interfaceA.getDates();
}
}
Przykład
private static InterfaceA interfaceA;
private static InterfaceB interfaceB;
private InterfaceA getInterfaceA() {
return interfaceA == null ? interfaceB.info() : interfaceA;
}
public final delegate InterfaceA from getInterfaceA();
}
Wyglądał by po skompilowaniu jak:
private static InterfaceA interfaceA;
private static InterfaceB interfaceB;
private InterfaceA getInterfaceA() {
return interfaceA == null ? interfaceB.info() : interfaceA;
}
public final String getName() {
return getInterfaceA().getName();
}
public final ArrayList<Date> getDates() {
return getInterfaceA().getDates();
}
}
Detale rozwiązania:
[private|protected|public|final|static|]
delegate
{[Interface|Class|method]}
from
[variable|method|function|null]
[exclude {Interface|Class|list of methods}]
[onnull throw new Exception(...)]
Dla kompilatora metoda wydelegowana jak i zadeklarowana jawnie były by identyczne, a co za tym idzie dwie identyczne nie mogły by występować w tym samym czasie.
Kompatybilność:
Wsteczna:
Taki sposób delegowania metod nie wpływa na już istniejący kod.
W przód:
Sam kod nie mógłby być interpretowany wstecz. Aczkolwiek nie ma znanych mi przeciwwskazań aby prze-kompilowane biblioteki nie mogły być używane.
0 comments / komentarz(y):
Post a Comment