Vererbung Countable mit Vererbung

eclipseworker

Bekanntes Mitglied
Ich möchte gerne ganz genau die Instanzen mehrere Klassen zählen, dazu habe ich folgendes mir überlegt:
Java:
public class InstanceCounter {
 
    private int instances;
    private final String nameOfCountedObject;
 
    public InstanceCounter(String objectName){
        instances=0;
        nameOfCountedObject=objectName;
    }
 
    public String getNameOfCountedObject(){
        return nameOfCountedObject;
    }


    public void increaseInstanceCounter(){
        instances++;
    }
 
    public void restetCounter(){
        instances=0;
    }
 
    public boolean noInstance(){
        return instances==0;
    }

    public void reduceInstanceCounter(){
        if(instances>0){
            instances--;
        }
    }

    public int getNumberOfInstances(){
        return instances;
    }

    /* (non-Javadoc)
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append("InstanceCounter [countedObject=");
        if (nameOfCountedObject != null) {
            builder.append("nameOfCountedObject=");
            builder.append(nameOfCountedObject);
        }
        builder.append(", instances=");
        builder.append(instances);
        builder.append("]");
        return builder.toString();
    }
}
Eine Counter Klasse, verwaltet in einer Map Wrapperklasse:
Java:
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class InstanceCounterSingletonList {
 
    private Map<String, InstanceCounter> map;

    public InstanceCounterSingletonList() {
        map = new ConcurrentHashMap<String, InstanceCounter>();
    }
 
    public InstanceCounter getInstanceCounterForClass(String classname, boolean increase){
        InstanceCounter returnCounter;
        if(map.containsKey(classname)){
            returnCounter=map.get(classname);
        }else{
            returnCounter=new InstanceCounter(classname);
            map.put(classname, returnCounter);
        }
        if(increase){
            returnCounter.increaseInstanceCounter();
        }
        return returnCounter;
    }
 
    public InstanceCounter getInstanceCounterForClass(String classname){
       return getInstanceCounterForClass(classname, false);
    }

    public void increaseInstanceCounterForClass(String classname){
        getInstanceCounterForClass(classname).increaseInstanceCounter();
    }
 
    public void restetCounterForClass(String classname){
        getInstanceCounterForClass(classname).restetCounter();
    }
 
    public boolean noInstanceOfClass(String classname){
        return getInstanceCounterForClass(classname).noInstance();
    }

    public void reduceInstanceCounterForClass(String classname){
        getInstanceCounterForClass(classname).reduceInstanceCounter();
    }

    public int getNumberOfInstancesForClass(String classname){
        return getInstanceCounterForClass(classname).getNumberOfInstances();
    }
}
Man bemerke, dass ich ConcurrentHashMap genommen habe, wenn möglich soll das ganze Thread sicher sein.
Nun die Liste sollte Möglichst auch nicht doppelt vorkommen, und das Interface hat sich Singleton für sie angeboten:
Java:
/**
* Acts as a Singleton for the InstanceCounterSingletonList itself, countable things should easily
* tell their names.
*/

public interface Countable {
 
    InstanceCounterSingletonList instanceCounterList=new InstanceCounterSingletonList();
 
    public String getClassName();
 
    public static InstanceCounter createInstanceCounter(String callingName){
        return instanceCounterList.getInstanceCounterForClass(callingName, true);
    }
 
    public static InstanceCounter getInstanceCounter(String callingName){
        return instanceCounterList.getInstanceCounterForClass(callingName);
    }
 
    public static void increaseInstanceCounter(String callingName){
        instanceCounterList.increaseInstanceCounterForClass(callingName);
    }
 
    public static void restetCounter(String callingName){
        instanceCounterList.restetCounterForClass(callingName);
    }
 
    public static boolean noInstance(String callingName){
        return instanceCounterList.noInstanceOfClass(callingName);
    }

    public static void reduceInstanceCounter(String callingName){
        instanceCounterList.reduceInstanceCounterForClass(callingName);
    }

    public static int getNumberOfInstances(String callingName){
        return instanceCounterList.getNumberOfInstancesForClass(callingName);
    }
 
    public static InstanceCounter createInstanceCounter(Countable calling){
        return instanceCounterList.getInstanceCounterForClass(calling.getClassName(), true);
    }
 
    public static InstanceCounter getInstanceCounter(Countable calling){
        return instanceCounterList.getInstanceCounterForClass(calling.getClassName());
    }
 
    public static void increaseInstanceCounter(Countable calling){
        instanceCounterList.increaseInstanceCounterForClass(calling.getClassName());
    }
 
    public static void restetCounter(Countable calling){
        instanceCounterList.restetCounterForClass(calling.getClassName());
    }
 
    public static boolean noInstance(Countable calling){
        return instanceCounterList.noInstanceOfClass(calling.getClassName());
    }

    public static void reduceInstanceCounter(Countable calling){
        instanceCounterList.reduceInstanceCounterForClass(calling.getClassName());
    }

    public static int getNumberOfInstances(Countable calling){
        return instanceCounterList.getNumberOfInstancesForClass(calling.getClassName());
    }
 
    public static InstanceCounterSingletonList getCounterList(){
        return instanceCounterList;
    }
}
Das ganze funktioniert auch gut, aber ich habe 1 Problem:
Vererbung, wenn ich folgende 2 Klassen habe:
Java:
public class CountableA implements Countable
{
 
    public String getClassName(){
        return this.getClass().getName();
    }

    /**
     * Constructor for objects of class CountableA
     */
    public CountableA() {
   System.out.println(Countable.createInstanceCounter(this));
    }
}
und
Java:
public class CountableAA extends CountableA{

    /**
     * Constructor for objects of class CountableAA
     */
    public CountableAA()
    {
        super();
System.out.println(Countable.createInstanceCounter(this.getClass().getName()));
    }
}
ist der Output wenn ich ein CountableAA erstelle:
Code:
InstanceCounter [countedObject=nameOfCountedObject=CountableAA, instances=1]
InstanceCounter [countedObject=nameOfCountedObject=CountableAA, instances=2]
statt dem eigentlichen gewünschten:
Code:
InstanceCounter [countedObject=nameOfCountedObject=CountableA, instances=1]
InstanceCounter [countedObject=nameOfCountedObject=CountableAA, instances=1]
Ich weiß schon, dass irgendwie das getName sich nur um die Aufrufende Instanz kümmert, nicht um die Klasse wo es drinnen steht, aber kann man das entsprechend besser machen?
Diese ganze Möglichkeit im Interface auch direkt den String zu übergeben, gehen schon ein bisschen in diese Richtung, aber ich habe gehofft, dass ich drumherum komme die Namen hart coden zu müssen. Und vorallem was mache ich bei abstrakten Klassen? Auch kann ich es im Interface erzwingen, dass eine untere Klasse wie zum Beispiel CountableAA ihre eigenen Methoden verwenden muss?
 
Zuletzt bearbeitet:

Flown

Administrator
Mitarbeiter
Ich würde das eher über eine Factory machen, da das hier ein wenig gegen das SRP verstößt.
Die Factory mit den Klassen in ein package werfen, Konstruktoren auf package-private (ohne Modifier) und dann sieht das vl. so aus:
Java:
public class Test {
  
  public static void main(String... args) {
    var instance = StatisticsFactory.getInstance();
    var countA = instance.createCountableA();
    var countB = instance.createCountableB();
    System.out.println(instance);
  }
}
final class StatisticsFactory {
  private static StatisticsFactory INSTANCE = new StatisticsFactory();
  private Map<Class<?>, Integer> countings;
  
  private StatisticsFactory() {
    this.countings = new ConcurrentHashMap<>();
  }
  
  public static StatisticsFactory getInstance() {
    return INSTANCE;
  }
  
  public CountableA createCountableA() {
    return count(new CountableA());
  }
  
  public CountableB createCountableB() {
    return count(new CountableB());
  }
  
  private <T> T count(T o) {
    countings.merge(o.getClass(), 1, Integer::sum);
    return o;
  }
  
  @Override
  public String toString() {
    return countings.entrySet().stream()
        .map(e -> String.format("%s: %d", e.getKey(), e.getValue()))
        .collect(Collectors.joining("\n"));
  }
}

class CountableA {
  
  CountableA() {
  }
}

class CountableB extends CountableA {
  CountableB() {
    super();
  }
}
 

eclipseworker

Bekanntes Mitglied
Ich würde das eher über eine Factory machen, da das hier ein wenig gegen das SRP verstößt.
Die Factory mit den Klassen in ein package werfen, Konstruktoren auf package-private (ohne Modifier) und dann sieht das vl. so aus:
Java:
public class Test {
 
  public static void main(String... args) {
    var instance = StatisticsFactory.getInstance();
    var countA = instance.createCountableA();
    var countB = instance.createCountableB();
    System.out.println(instance);
  }
}
final class StatisticsFactory {
  private static StatisticsFactory INSTANCE = new StatisticsFactory();
  private Map<Class<?>, Integer> countings;
 
  private StatisticsFactory() {
    this.countings = new ConcurrentHashMap<>();
  }
 
  public static StatisticsFactory getInstance() {
    return INSTANCE;
  }
 
  public CountableA createCountableA() {
    return count(new CountableA());
  }
 
  public CountableB createCountableB() {
    return count(new CountableB());
  }
 
  private <T> T count(T o) {
    countings.merge(o.getClass(), 1, Integer::sum);
    return o;
  }
 
  @Override
  public String toString() {
    return countings.entrySet().stream()
        .map(e -> String.format("%s: %d", e.getKey(), e.getValue()))
        .collect(Collectors.joining("\n"));
  }
}

class CountableA {
 
  CountableA() {
  }
}

class CountableB extends CountableA {
  CountableB() {
    super();
  }
}
Ich habe den Code "ausgebessert" und laufen lassen:
Java:
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

public class Test {
 
  public Test(){}
  public static void main(String[] args) {
    StatisticsFactory instance = StatisticsFactory.getInstance();
    CountableA countA = instance.createCountableA();
    CountableB countB = instance.createCountableB();
    System.out.println(instance);
  }
}
final class StatisticsFactory {
  private static StatisticsFactory INSTANCE = new StatisticsFactory();
  private Map<Class<?>, Integer> countings;
  private StatisticsFactory() {
    this.countings = new ConcurrentHashMap<>();
  }
  public static StatisticsFactory getInstance() {
    return INSTANCE;
  }
  public CountableA createCountableA() {
    return count(new CountableA());
  }
  public CountableB createCountableB() {
    return count(new CountableB());
  }
  private <T> T count(T o) {
    countings.merge(o.getClass(), 1, Integer::sum);
    return o;
  }
  @Override
  public String toString() {
    return countings.entrySet().stream()
        .map(e -> String.format("%s: %d", e.getKey(), e.getValue()))
        .collect(Collectors.joining("\n"));
  }
}

class CountableA {
  CountableA() {
  }
}

class CountableB extends CountableA {
  CountableB() {
    super();
  }
}
Der Output ist:
Code:
class CountableA: 1
class CountableB: 1
gwünscht wäre aber:
Code:
class CountableA: 2
class CountableB: 1
Da B eine Supklasse von A ist.
 

Flown

Administrator
Mitarbeiter
Das ist ja das gemeinte SRP oder?
Äh ja.
Ich habe den Code "ausgebessert" und laufen lassen:
Ist Java 10
gwünscht wäre aber:
Da B eine Supklasse von A ist.
Java:
private <T> T count(T o) {
  for(Class<?> clazz = o.getClass(); clazz.getSuperclass() != null; clazz = clazz.getSuperclass()) {
    countings.merge(clazz, 1, Integer::sum);
  }
  return o;
}
Dann sollte es gehen.
 

eclipseworker

Bekanntes Mitglied
Interessant, wusste ich nicht.
Java:
private <T> T count(T o) {
  for(Class<?> clazz = o.getClass(); clazz.getSuperclass() != null; clazz = clazz.getSuperclass()) {
    countings.merge(clazz, 1, Integer::sum);
  }
  return o;
}
Dann sollte es gehen.
Sehr schön. Zwei fragen:
1) Wenn die Superclass gleich null ist sind wir ohne hin schon im Objekt oder?
2) Diese Schleife iteriert also über den ganzen Vererbungsbaum bis hinauf zum Objekt oder?
 

Flown

Administrator
Mitarbeiter
1) Wenn die Superclass gleich null ist sind wir ohne hin schon im Objekt oder?
Lt. Dokumentation
Returns the Class representing the direct superclass of the entity (class, interface, primitive type or void) represented by this Class. If this Class represents either the Object class, an interface, a primitive type, or void, then null is returned. If this object represents an array class then the Class object representing the Object class is returned.
2) Diese Schleife iteriert also über den ganzen Vererbungsbaum bis hinauf zum Objekt oder?
Sozusagen
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
U Vererbung?! Allgemeine Java-Themen 15
temi Problem mit Aufrufreihenfolge bei Vererbung Allgemeine Java-Themen 3
MiMa Vererbung und Komposition?? Allgemeine Java-Themen 38
Kirby.exe Vererbung bei Generics Allgemeine Java-Themen 7
L Vererbung Verständnis Probleme Vererbung Allgemeine Java-Themen 2
W Generics + Vererbung Allgemeine Java-Themen 47
M Vererbung mithilfe von Bluej Allgemeine Java-Themen 3
M List -Tableview-Javafx-Vererbung Allgemeine Java-Themen 35
A Vererbung Selbstreferenzparameter Allgemeine Java-Themen 14
D Thema: Vererbung Ober-/Unterklassen Allgemeine Java-Themen 16
D Frage zu Vererbung Allgemeine Java-Themen 5
N Vererbung mit GUI Allgemeine Java-Themen 9
J 2 Fragen zur Vererbung Allgemeine Java-Themen 5
T Javaklassen und vererbung Allgemeine Java-Themen 32
F Vererbung Allgemeine Java-Themen 5
Neumi5694 Vererbung Restriktive Vererbung Allgemeine Java-Themen 4
A Vererbung Übungsaufgabe Vererbung - Erstellung Klassenhierarchie Allgemeine Java-Themen 1
J Allgemeine Fragen zu Vererbung Allgemeine Java-Themen 1
kaoZ Generics und Vererbung Allgemeine Java-Themen 3
D Problem bei Vererbung abstrakter Klassen Allgemeine Java-Themen 6
D Object nach Vererbung mit Class Object überprüfen Allgemeine Java-Themen 4
T Super Klasse Vererbung Problem :/ Allgemeine Java-Themen 10
L Unabhängige Auslieferung bei Vererbung Allgemeine Java-Themen 20
S MVC - Vererbung Allgemeine Java-Themen 4
C Enums und Vererbung Allgemeine Java-Themen 6
F Google Guice + Generics + Vererbung Allgemeine Java-Themen 5
D Unterschied Vererbung und Polymorphie? Allgemeine Java-Themen 4
K Vererbung ohne Basisklasse zu kennen Allgemeine Java-Themen 20
Da_Tebe ArrayList<xyz> Verschachtelung oder Vererbung? Allgemeine Java-Themen 6
faetzminator statische Variablen in Interface - Vererbung? Allgemeine Java-Themen 9
M OOP PropertyChangeListener - Vererbung oder Komposition? Allgemeine Java-Themen 5
S OOP Mehrfache Vererbung von abstrakten Klassen Allgemeine Java-Themen 7
G Designfrage Vererbung ja oder nein Allgemeine Java-Themen 9
S equals - Identität ändern bei Vererbung? Allgemeine Java-Themen 5
dayaftereh Vererbung Hilfe Allgemeine Java-Themen 2
D Vererbung, Reflection und automatischer Methodenaufruf Allgemeine Java-Themen 24
A PropertyChangeListener Vererbung Allgemeine Java-Themen 4
P DefaultTreeCellRenderer Vererbung Allgemeine Java-Themen 5
S Objekte die Objekte enthalten: Keine Vererbung Allgemeine Java-Themen 4
J Vererbung bei abstrakten Klassen Allgemeine Java-Themen 2
S Vererbung: Welche Methode wird verwendet? Allgemeine Java-Themen 9
L Checkstyle: Wann ist eine Methode für Vererbung entworfen? Allgemeine Java-Themen 13
S normale vererbung als interface Allgemeine Java-Themen 2
S statische Methoden und Vererbung Allgemeine Java-Themen 6
R Vererbung - doppelte Paint-Methode Allgemeine Java-Themen 4
R Vererbung mit Interface und Abstract Allgemeine Java-Themen 3
B Vererbung bei enums ? Allgemeine Java-Themen 3
W Frage zu Vererbung / konkretes Beispiel Allgemeine Java-Themen 4
F Vererbung von SessionBeans Allgemeine Java-Themen 3
O abstract, privat, Vererbung Allgemeine Java-Themen 29
L Annotations mit Vererbung Allgemeine Java-Themen 4
M Singleton und Vererbung? Allgemeine Java-Themen 45
T Problem mit Vererbung Allgemeine Java-Themen 3
V Vererbung und Schleifen Allgemeine Java-Themen 5
C Comparable + Vererbung Funktioniert nicht? Allgemeine Java-Themen 4
A Ansatz Objektorientierung, Methoden Vererbung Allgemeine Java-Themen 2
D Listen von Generischen Typen inkl. Vererbung Allgemeine Java-Themen 2
D Zugriffsmethode nach Vererbung ändern? Allgemeine Java-Themen 5
S Vererbung in UML Allgemeine Java-Themen 3
T Nochmal Frage zu Vererbung Interfaces etc. Allgemeine Java-Themen 10
Y Gedanken zur Vererbung Allgemeine Java-Themen 7
F Vererbung, Generizität und Collections. Allgemeine Java-Themen 7
G Frage zu statischen Variablen bei Vererbung Allgemeine Java-Themen 15
F Vererbung Allgemeine Java-Themen 5
S Vererbung von mehreren Klassen? Allgemeine Java-Themen 5
C enum und Vererbung Allgemeine Java-Themen 3
K Problem mit Vererbung - Kein wirklicher Nutzen. Allgemeine Java-Themen 10
G vererbung vs benutzung Allgemeine Java-Themen 7
L Vererbung klappt nicht Allgemeine Java-Themen 5
W Probleme mit Arrays und Vererbung ! Allgemeine Java-Themen 5
M vererbung einer "selbst-instanzierungs-klasse" Allgemeine Java-Themen 16
J Vererbung. Allgemeine Java-Themen 8
H Frage zur Vererbung Allgemeine Java-Themen 5
S private Instanzvaribalen bei "Innerer-Vererbung" Allgemeine Java-Themen 9
H Vererbung auch ohne erzeugung einer Instanz möglich? Allgemeine Java-Themen 3
M frage zur vererbung Allgemeine Java-Themen 12
G Generics und Vererbung. Allgemeine Java-Themen 21
M Vererbung von Hashtables Allgemeine Java-Themen 5
C dynamische Vererbung Allgemeine Java-Themen 6

Ähnliche Java Themen

Neue Themen


Oben