10 March 2009

Delegation proposal

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:

public abstract class ClassA implements InterfaceA {

  InterfaceA ia = ...;
  
  public delegate InterfaceA{
    return ia;
  }

}

ADVANCED EXAMPLE:

public abstract class ClassA implements InterfaceA {

  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

Delegation proposal

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

public interface InterfaceA extends Iterable<String> {

  String getName();

  ArrayList<Date> getDates();

}
public interface InterfaceB {

  public InterfaceA info();

}
public abstract class ClassA implements InterfaceA {

  public int  delta  = 0;

  abstract public void printState();

}

Przykład

public class Sample_01 {

  private static InterfaceA interfaceA;
  
  public static delegate InterfaceA from interfaceA onnull {throw new NullPointerException(InterfaceA.class.getSimpleName());};
  
}

Wyglądał by po skompilowaniu jak:

public class Sample_01 {

  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

public class Sample_02 {

  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:

public class Sample_02 {

  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.

Linki:

0 comments / komentarz(y):

Post a Comment