Re: Objekt 'einfrieren'?



"Ivan Dolvich" skribis:

Gibts da eine möglichkeit das in der Abstrakten Klasse irgendwie
festzulegen, oder geht das nur über den Umweg in alle Unterklassen rein
zu gehen und das in die Setter zu implementieren?

Du könntest vielleicht das Objekt durch ein anderes, unveränderliches
ersetzen. Dazu müssten aber alle Zugriffe aufs Objekt nie direkt,
sondern durch einen "Proxy" erfolgen.

[viel Code]

Ist etwas kompliziert, aber unserem Pattern-Professor würde es bestimmt
gefallen.

Hmm, den ImmutableFO würde ich weglassen, und stattdessen
in der set-Methode des Proxys ein frozen-Flag abfragen.
(Und außerdem wäre mir eine Exception lieber als einfach
nichts zu tun, aber das geht ja bei dir auch einfach.)


Damit das aber ordentlich funktioniert, sollte man das ganze
generisch machen, mit java.lang.reflect.Proxy.

Hier ein Beispiel.

---
import java.lang.reflect.*;

public interface Freezable {

/**
* Friert das Objekt ein.
*/
public void freeze();
}

/**
* wird von set-Methoden geworfen, wenn das
* entsprechende Objekt eingefroren wird.
*/
public class FrozenException extends RuntimeException {

FrozenException(String message) {
super(message);
}
}

public class Freezer {

/**
* @param interfaceType das Class-Objekt des Interfaces E.
* @param delegate an dieses Objekt werden alle Aufrufe von
* in E deklarierten Methoden des Ergebnis-Objektes
* weitergeleitet, ebenso wie hashcode, toString
* und equals.
*
* @returns ein Objekt, welches neben E auch noch Freezable
* implementiert. Ab dem Aufruf von freeze() funktionieren die
* set-Methoden nicht mehr, alle anderen Methodenaufrufe werden
* aber an delegate weitergeleitet.
*/
public <E> E createFreezable(final Class<E> interfaceType, final E delegate) {
InvocationHandler handler =
new InvocationHandler() {
boolean frozen;
Object invoke(Object proxy, Method method, Object[] args)
throws Throwable
{
String name = method.getName();
if (name.equals("freeze") &&
args.length == 0) {
frozen = true;
return null;
}
if (frozen && name.startsWith("set")) {
throw new FrozenException("Objekt eingefroren, method " + name +
" nicht erlaubt");
}
return method.invoke(delegate, args);
}
};
Object proxy =
Proxy.newProxyInstance(interfaceType.getClassLoader(),
new Class[] { interfaceType, Freezable.class },
handler);
return interfaceType.cast(proxy);
}

}

class Test {


public static void main(String[] egal) {
// zum Testen nehme ich mal das Interface und
// die MutableFO-Klasse von Ivan

x1 = new X(42);
x2 = new X(13);

FreezyObject fo =
new Freezer().createFreezable(FreezyObject.class, new MutableFO());

fo.setX(x1); // OK

// einfrieren:
((Freezable)fo).freeze();


try {
fo.setX(x2); // gibt eine Exception
}
catch (FrozenException ex) {
ex.printStackTrace();
}

// get geht aber:
System.out.println(fo.getX());
}
}
---
(Nicht ausprobiert, eventuell müssen noch ein paar
Syntax(tipp)fehler behoben werden.)

Leider gibt es in Java keine Schnittmengen-Typen,
so dass die Signatur von createFreezable sagen könnte,
dass das Ergebnis-Objekt auch Freezable ist - dadurch
müssen wir zum Einfrieren auf Freezable casten.


Falls man keine Exception will, kann man in der
entsprechenden Zeile auch einfach ein "return null;"
machen.

Das ganze geht natürlich daneben, wenn sich das Objekt
noch über andere Methoden als solche, deren Namen mit
"set" beginnt, ändern lässt - dies ist etwa bei ziemlich
allen Interfaces in java.util der Fall (sofern es
überhaupt etwas zu ändern gibt).


Paul
--
Eine Signatur sollte mit "-- " abgetrennt werden,
wobei OjE meist das " " verschluckt. Eine nicht
korrekt abgetrennte Signatur ist keine Signatur ...
.



Relevant Pages

  • 7.0 wishlist?
    ... Any object can be used where an interface type is expected if it has the right set of method signatures, whether or not it "implements" the interface using that keyword. ... the algorithm name is hard-coded and so this exception ... Most invocations of runnables ... Allow subclassing an enum with the subclasses able to REMOVE (not ...
    (comp.lang.java.programmer)
  • Re: Remote Debugging ASP.net 2.0 Web Service (no symbols loaded?)
    ... John Saunders [MVP] ... (either return values or one line error messages - typically exception ... this interface are somewhat ambiguous, ... information in the HTTP response from these web methods, ...
    (microsoft.public.vsnet.debugging)
  • Re: Closures ... again!
    ... Ich schloss daraus, dass man jetzt ein Interface definieren muss, wenn man eine Variable haben möchte, die ein Closure-Objekt enthält. ... throws E extends Exception> { ... Damit darf die Closure dann auch nicht-finale lokale Variablen benutzen. ... Das finde ich beknackt bzw. verstehe die Motivation nicht, denn das ist IMHO Sache des Closure-Objekts und nicht der Stelle, die eine Closure entgegen nimmt. ...
    (de.comp.lang.java)
  • Re: Interface und Exception
    ... C# kann man z.B. auch ohne WCF verwenden. ... hier geht es um die "Interfaces und Exception" ... #In meinem Programm definiere ich ein Interface: ... nicht C++ mit WCF oder einem anderen Framework. ...
    (microsoft.public.de.german.entwickler.dotnet.csharp)
  • Re: Com Exception from .Net Application.
    ... It will generate a wrapper assemble for the COM component so I can just use it in C#. ... Here i am getting an exception with the below statement ... Unable to cast COM object of type 'System.__ComObject' to interface type ... QueryInterface call on the COM component for the interface with IID ...
    (microsoft.public.dotnet.languages.csharp)