EnumSet erweitern ...

Status
Nicht offen für weitere Antworten.

boesi

Aktives Mitglied
moin

Ich möchte die Klasse EnumSet um eine Methode
Java:
boolean containsAny(Collection<E> c)
erweitern - irgendein Element aus c soll im Set vorhanden sein. Und das natürlich möglichst ohne EnumSet komplett neu zu implementieren.

Tja die Frage ist nun: Wie geht man/frau da am besten vor?

Ich hab mir da natürlich schon ein paar Gedanken zu gemacht - bin aber im Moment der Meinung, das geht mit der 2. Bedingungen nicht. Meine Gedanken werde ich in einem 2. Posting schreiben - jetzt will ich erstmal eine Diskussion lostreten ... (wenn denn jemand mit diskutieren will 😉)


cu boesi

PS: ja ich weiß so wirklich "Anfänger"-tauglich ist das Thema nicht, aber zumindest für mich sehr "Basics"
 
Mach Dir doch einfach eine Util Funktion dafür: [c]static boolean containsAny(Collection<E> c, EnumSet<E> set)[/c]
 
Mach Dir doch einfach eine Util Funktion dafür: [c]static boolean containsAny(Collection<E> c, EnumSet<E> set)[/c]
Das wäre natürlich möglich und wird wohl praktisch auch darauf hinaus laufen - aber hey wir sind doch hier in einer strikt objektorientieren Welt mit Vererbung und all diesem Quatsch ... 😉
 
List ist ein Interface und es gibt zig verschiedene Listen,
niemand würde von allen erben wollen um dort die Sortierung einzeln einzubauen
->
Collections.sort(list)

steht nicht die Aggregation noch über der Vererbung?
 
List ist ein Interface und es gibt zig verschiedene Listen,
niemand würde von allen erben wollen um dort die Sortierung einzeln einzubauen
->
Collections.sort(list)

steht nicht die Aggregation noch über der Vererbung?
Ich bin in UML nicht ganz fit, deswegen hilf mir doch mal bitte auf die Sprünge, wie du hier auf Aggregation kommst. Die Enum-Konstanten sind zwar Teil des EnumSets und daher liegt hier wohl eine Aggregation vor - aber was hat das mit der gewünschten Funktion containsAny zu tun? Wäre das nicht eher eine Spezialisierung bzw eine Erweiterung? Dass das nicht geht, liegt ja an der konkreten Implementierung von EnumSet.

Ob die Funktion sort nun direkt in das Interface List oder zB SortedList gehört oder in eine Hilfsklasse als statische Methode - darüber kann man beliebig lang streiten - aber immerhin ist die Klasse Collections konsequent umgesetzt. Aber genau diese Konsequenz würde meiner Hilfsmethode containsAny fehlen - was ist denn der Unterschied zwischen containsAll und containsAny?


cu boesi
 
was ist denn der Unterschied zwischen containsAll und containsAny?
bei all muessen alle elemente vorhanden sein bei any reicht es wenn mind. 1

was Slater meinte ist dass
Java:
public class MyList {
    private OtherClass theClass;
}
vorzuziehen gegenueber
Java:
public class MyList extends OtherClass {
}
ist

edit: wobei ich zugeben muss dass ich seinen Post mit deiner Frage nicht ganz in Zusammenhang bekomme ;-)
 
bei all muessen alle elemente vorhanden sein bei any reicht es wenn mind. 1
Das ist mir schon klar - ich hab ja die Bedeutung von containsAny selbst definiert. Worauf ich eigentlich hinaus wollte: Warum soll es für den Programmierer, der containsAll und containsAny verwenden würde, logisch sein, dass die Art des Aufrufs sich unterscheidet. Ich muß ja schließlich auch an die Wartbarkeit meines Codes denken ...

was Slater meinte ist dass
Java:
public class MyList {
    private OtherClass theClass;
}
vorzuziehen gegenueber
Java:
public class MyList extends OtherClass {
}
ist

edit: wobei ich zugeben muss dass ich seinen Post mit deiner Frage nicht ganz in Zusammenhang bekomme ;-)
Wobei ein derartiger Wrapper* durchaus eine Lösung sein könnte ... *denkpause* ... verdammt nein das würde auch nicht einfach so funktionieren - weil noneOf Objekte erzeugt, die vom orginalen EnumSet abgeleitet sind und meine Methode containsAny wieder nicht enthalten würden. Ich müßte also doch Teile von EnumSet neuimplementieren.

* um mal einen Begriff aus dem Bereich der Entwurfsmuster zu verwenden, ist für mich deutlich näher an der praktischen Lösung von Problemen des Programmieralltags als UML


cu boesi
 
bevor ich meine Gedanken zu diesem Thema wiedergebe: Wieso
ist einzige Constructor von EnumSet protected? Das verhindert effektiv, dass ich EnumSet selbst implementieren kann.

Hier nun meine etwas ausführliche Analyse dieser Geschichte: EnumSet ist eine abstrakte Klasse mit einer Reihe von statischen Factory-Methoden, die ein konkretes Objekt der Klasse erzeugen. Dazu gibt's noch eine ganze Reihe von Methoden, die von den abgeleiteten Klassen implementiert werden müssen. Interessant ist die Methode
Java:
public static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType)
Diese liefert abhängig von der Größe des Enum-Universiums ein Objekt einer Klasse, die wiederum EnumSet implementiert.

Bezüglich der Objektorientierung seh ich hier mindestens 2 Brüche:
  1. EnumSet kennt die Klassen, die von ihr abgeleitet sind.
  2. Ich kann EnumSet nicht selbst implementieren, ohne meine neue Klasse in das Package java.util zu stellen. Überhaupt erschließt sich mir der Sinn von protected Konstrukturen bei einer abstrakten Klasse nicht wirklich.
Meine gewünschte Methode containsAny kann man nun von 2 Seiten aus betrachten:
  1. Wenn man sich den Objektbaum vorstellt, will ich quasi zwischen EnumSet und den konkreten Implementierungen eine weitere Klasse einschieben. Es ist offensichtlich, dass das nicht geht. In Java sowieso nicht und auch sonst ist der Gedanke eher merkwürdig.
  2. Ich will doch EnumSet einfach nur um eine Methode erweitern. Dass EnumSet unterschiedliche Implementierungen verwendet, weiss ich als Anwender der Klasse doch gar nicht (und soll ich ja auch nicht wissen).
 
> verdammt nein das würde auch nicht einfach so funktionieren - weil noneOf Objekte erzeugt, die vom orginalen EnumSet abgeleitet sind

das gilt genauso für eine SubKlasse, spricht also nicht gegen einen Wrapper

> Bezüglich der Objektorientierung seh ich hier mindestens 2 Brüche:
>
> 1. EnumSet kennt die Klassen, die von ihr abgeleitet sind.
> 2. Ich kann EnumSet nicht selbst implementieren,

man könnte behaupten, dass 1 und 2 zusammengehören 😉
manche Dinge soll man in Java eben nicht erweitern, String ist final, hier hat man diesen Trick verwendet,
Enums sind ebenso begrenzt
 
Zuletzt bearbeitet von einem Moderator:
EnumSet kennt die Klassen, die von ihr abgeleitet sind
ist nicht unbedingt schlecht... wie du schon sagst sind es Factory methoden, die dem Aufrufer unwissend lassen was fuer eine Implementierung nun genau dahinter steckt - was fuer ihn ja auch voellig uninteressant ist, hauptsache es ist ein EnumSet

Ich kann EnumSet nicht selbst implementieren, ohne meine neue Klasse in das Package java.util zu stellen. Überhaupt erschließt sich mir der Sinn von protected Konstrukturen bei einer abstrakten Klasse nicht wirklich.
weil man eben verhindern will dass die Klasse ausserhalb des packages instanziert werden kann bzw vererbt werden kann. Enkapselung ist ein enorm starkes und wichtiges Element in einem guten Design
 
ist nicht unbedingt schlecht... wie du schon sagst sind es Factory methoden, die dem Aufrufer unwissend lassen was fuer eine Implementierung nun genau dahinter steckt - was fuer ihn ja auch voellig uninteressant ist, hauptsache es ist ein EnumSet


weil man eben verhindern will dass die Klasse ausserhalb des packages instanziert werden kann bzw vererbt werden kann. Enkapselung ist ein enorm starkes und wichtiges Element in einem guten Design
Jetzt werd ich mal polemisch: Kapselung oder jedes andere Konzept zum Selbstzweck ist ein Zeichen für verdammt schlechtes Design.

Letztendlich vermischt EnumSet die beiden Konzepte Factory und Interface, dabei sollten die eigentlich wie zB bei BorderFactory und dem Interface Border klar getrennt sein.
 
Off Topic:

In einer vernünftigen Sprache löst man solche Probleme so: Pimp my Library.
Scala ist definitiv eine der interessantesten Sprachen, die in den letzten Jahren so erschienen sind. Wenn nur die geschweiften Klammern nicht wären und die Doppelpunkte an der richtigen Stelle. Dafür ist das Fehlen von Semikolons eine wahre Wohltat :toll:

Aber da ich aktuell auf Java festgenagelt bin und das Ding hier Java-forum.org heißt, führt das tatsächlich am Thema vorbei. Also gib's noch Lösungsansätze in Java?
 
hae ? was ? sorry versteh ich nicht..

natuerlich muss groovy installiert sein und java ....
Eh ich Groovy installier, nehm ich lieber gleich Scala (oder noch lieber Python). Aber wie schon gesagt, steht mir in meiner praktischen Arbeit leider weder das eine noch das andere zur Verfügung. Aber ich will trotzdem Klassen erweitern, will die Standardbibliothek um Funktionen erweitern, die sich genau wie die bereits vorhandenen nutzen lassen uswusf.

Und da bleibt wohl nur eine Portierung nach Plain Old Java ...
 
ich muss sagen ich versteh immer noch nicht warum du unbedingt enumset neu implementieren willst
Java:
public class RR<E extends Enum<E>> {
    private final EnumSet<E> _set;

    public RR(EnumSet<E> set) {
        _set = set;
    }

    public boolean containsAny(Collection<E> collection) {
        for (E e : collection) {
            if (_set.contains(e)) {
                return true;
            }
        }
        return false;
    }

    public static void main(String[] args) {
        RR<Foo> r = new RR<Foo>(EnumSet.of(Foo.bar));
        List<Foo> list = new ArrayList<Foo>();
        System.out.println(r.containsAny(list));
        list.add(Foo.bar);
        System.out.println(r.containsAny(list));
    }

    enum Foo {
        foo, bar
    }
}
 
ich muss sagen ich versteh immer noch nicht warum du unbedingt enumset neu implementieren willst
Das will ich ja gerade nicht. Ich will einfach nur eine Methode containsAny, die sich genau wie containsAll verwenden läßt. Warum ich das will?
1. Weil sich
Java:
if (this.avaiable.contains(PrintFunctions.SURVEY) || this.avaiable.contains(PrintFunctions.ZERTIFIKAT) ||
				this.avaiable.contains(PrintFunctions.RESULTS) || this.avaiable.contains(PrintFunctions.SKILLS)||
				this.avaiable.contains(PrintFunctions.JOBS) || this.avaiable.contains(PrintFunctions.CONSULTING)) {
echt beschissen liest und 2.
Java:
if (this.avaiable.containsAll(EnumSet.of(PrintFunctions.VORLAGE, PrintFunctions.SURVEY)) { ...
} else if (Helper.containsAny(this.avaiable, EnumSet.of(PrintFunctions.RESULTS, PrintFunctions.SKILLS))) {
noch viel schlimmer ist.
 
Zuletzt bearbeitet:
fakt ist - es geht nicht... ergo bleibt dir nur Delegation uebrig oder wie byto schrieb eine utility
 
Das will ich ja gerade nicht. Ich will einfach nur eine Methode containsAny, die sich genau wie containsAll verwenden läßt. Warum ich das will?
1. Weil sich
Java:
if (this.avaiable.contains(PrintFunctions.SURVEY) || this.avaiable.contains(PrintFunctions.ZERTIFIKAT) ||
				this.avaiable.contains(PrintFunctions.RESULTS) || this.avaiable.contains(PrintFunctions.SKILLS)||
				this.avaiable.contains(PrintFunctions.JOBS) || this.avaiable.contains(PrintFunctions.CONSULTING)) {
echt beschissen liest.
und 2.
Stand ja auch nie zur Debatte...

Ich finde, diesen beiden Varianten lesen sich genau gleich gut:

Java:
if (EnumUtils.containsAny(available, Arrays.asList(PrintFunctions.SURVEY, PrintFunctions.ZERTIFIKAT, ...)) {
  // blub
}
Java:
if (available.containsAny(Arrays.asList(PrintFunctions.SURVEY, PrintFunctions.ZERTIFIKAT, ...)) {
  // blub
}
 
oder auch
Java:
if (EnumUtils.containsAny(available, PrintFunctions.SURVEY, PrintFunctions.ZERTIFIKAT, ...) {
  // blub
}
mit einem ...-Parameter

edit: wie ihn sonst Arrays.asList natürlich verwenden würde 😉
 
Status
Nicht offen für weitere Antworten.

Zurück
Oben