2017-11-29 4 views
1

In einer abstrakten Klasse genannt wird Ich habe ein Predicate Feld, das gemeint ist eine Kombination aus einer unbekannten Anzahl von anderen Predicate s zu sein. Das Verbinden der Prädikate funktioniert gut, aber ich versuche, eine Möglichkeit zu haben, zu wissen, wann das Prädikat initialisiert wurde (oder vielmehr, nur um zu wissen, ob es initialisiert wurde oder nicht).Call-Methode einmal nach einem der wenigen überladenen Methoden

Hier ist ein kleines Beispiel von dem, was ich spreche.

public abstract class LimitedSystem implements Moveable { 

private Predicate<Double> limits; 
private final boolean initialized; 

public void setLimits(SingleLimit... limits) { 

    List<Predicate<Double>> limitsList = Arrays.asList(limits); 
    this.limits = limitsList.stream().reduce(Predicate::and).orElse(x -> true); 
} 

public void setLimits(TwoLimits limits) { 
    this.limits = limits; 
} 
... 

ich nach Möglichkeiten suchen initialized zu true einmal einzustellen (und nur einmal, daher der final Ich denke, habe ich es richtig) Alle setLimits wurden aufgerufen (sie sind überlastet).

Ich habe andere setLimits Methoden, aber aus Gründen der generischen Code, ich möchte keine initialized am Ende jeder der überladenen Methoden setzen.

Also meine Frage ist, wie kann ich, in einer generischen Weise, den Wert initialized nach einer der setLimits Methoden wurde aufgerufen.

Meine erste Idee war, zu versuchen, die setLimits in eine generische Methode zu wickeln, die die richtige Überladung durch den Parameter aufrufen würde, die es bekommt, und dann initialized in dieser Methode ändern. Aber ich bin mir nicht sicher, ob das eine gute Idee ist.

Einige andere Idee, die ich aus einer anderen Frage bekam 1 war ähnlich der setLimits in irgendeiner Schnittstelle oder etwas zu setzen. Aber ich bin mir nicht sicher, wie nützlich das sein könnte.

Also, wie könnte dies erreicht werden?

(Auch, wenn Sie irgendwelche Design-Probleme in diesem bemerken, bitte sagen Sie mir, weil ich in dieser Angelegenheit zu verbessern bin versucht)

+0

Wie ersetzen Sie SetLimits durch Konstruktoren? – Oleg

+0

Ich möchte Sie daran erinnern, dass endgültige Felder in der Deklarationszeile oder im Konstruktor gesetzt werden müssen. Sie können also ihren Wert nicht in einer zufälligen Methode zuweisen. Ich weiß, es ist nicht die wirkliche Frage. –

+0

@ Törpetestű oh. Das wusste ich auch nicht.Vielen Dank! – ItamarG3

Antwort

2

Es gibt keine Notwendigkeit für separate Felder:

private Predicate<Double> limits; 
private final boolean initialized; 

im Grunde ist

private Optional<Predicate<Double>> limits = Optional.empty(); 

wenn Sie initialized wollen true einmal limits eingestellt werden gesetzt, vorausgesetzt, Sie können garantieren, dass keine der setLimits Methoden es wieder auf Optional.empty() setzen kann. initialized == limits.isPresent().


Sie können nicht garantieren, dass ein Verfahren, in dem Körper einer überschriebene Methode aufgerufen wird; in jedem Fall ist dies eine Variante der .

Sie können es wie folgt tun:

abstract class Base { 
    final void setFoo(Object param) { // final, so can't be overridden. 
    setFooImpl(param); 
    thingThatMustBeCalled(); 
    } 

    protected abstract void setFooImpl(Object param); 

    final void thingThatMustBeCalled() { ... } 
} 

class Derived extends Base { 
    @Override protected void setFooImpl(Object param) { ... } 
} 

Aber es ist ziemlich hässlich.

+0

Ich wusste nicht, 'Optional' funktioniert so. Ich werde das jetzt versuchen. – ItamarG3

+0

Damit entfällt das Aufrufen einer Methode, nachdem eine überladene aufgerufen wurde. Hmph, ich frage mich immer noch, ob das möglich ist. aber das ist eine andere Frage als diese, also könnte ich bald eine andere (allgemeinere und doch etwas spezifischere) Frage stellen. (in einem anderen Beitrag, natürlich) – ItamarG3

+0

@ ItamarG3 siehe bearbeiten. –

Verwandte Themen