Storing methods identifiably in Java

Tags: , ,



I’m trying to come up with a solution to a problem where I want to store method references in some way so that I can invoke them when needed and remove them when I don’t need them on my list of methods.

The underlying goal here goes something like this:

I have a Person class:

public class Person {
    private String ref, name;
    private String fatherRef; // can be reference string (such as "#1#") or a literal text (such as "the guy next door")

    public Person(String ref, String name) {
        this.ref = ref;
        this.name = name;
    }

    public String getFatherRef() {return fatherRef;}

    public void setFatherRef(String ref) {
        fatherRef = ref;
    }

    ...
}

I make 2 instances of father and son and I set the father’s ref as fatherRef for the son using setFatherRef method. I keep both of them on a list. Now say the father’s object is deleted from the system and his ref becomes available for another person. To make sure the father is not referenced in the son’s object after he’s been deleted I came up with this:

I made an interface IRefSetter {public void setRef(String ref);} and I used it to make a ArrayList<IRefSetter> methods (such as setFatherRef or setMotherRef, etc.) and mapped that list using a father’s ref onto a HashMap<String,ArrayList<IRefSetter>> so that anytime I’m getting rid of any person I can look at their ref and see if it’s mapped to a list of methods that I can use to set their refs for all other Persons to null or “”.

In this example the map would have only one mapping of father’s ref to a list containing a single method referencing the setFatherRef from Person class. Now that would work fine but say I set the fatherRef to somebody else’s ref and add the method reference for that new person the same way as with the original father. But now I’m left with a HashMap containing under the original father’s ref a list on which I have a method stored to reset the son’s fatherRef if the original father is deleted. But that’s no longer necessary since the son now has a different father set with a different ref.

I can’t see a simple way of being able to identify which method on my list is son::setFatherRef because the lambda function that’s created each time I reference the method is different.

From that point I started looking into a very ugly kind of solution where instead of storing lambda functions matching my original IRefSetter interface I’m storing an Object reference to (in this case) son’s Person instance and a method name as a String along with it and attempt to match the correct method to my IRefSetter interface by hand (using Class and Method classes). But that’s a very ugly solution that instead of compiler errors would produce run-time errors which I don’t like and the whole thing doesn’t seem very OOP to me.

Am I missing a better solution here?

Answer

The better solution would be:

public class Person {
    private String ref, name;
    private Person father;
    private List<Person> children;

    ... a lot of obvious stuff here ...
}

Now when you remove a Person, you can look at that person’s father and then remove the Person from the father’s list of children, and also look at the removed person’s children and set the father for each to null. If you want to know the father’s ref just do father.ref or getFather().getRef().

I sense that you don’t want to do this for some reason, like it’s dirty or not OOP or something like that. But this is the solution that best uses the capabilities of the language and runtime library.

Other solutions tend to just be more complicated ways of doing this. In your example, instead of having a children member, you have created a separate HashMap in which the key is the father ref and the value is an array of setter methods, but you see that this is just the same: for every child-father relationship, there is an entry in a list associated with the father.

If you insist on your setter strategy, a simple way to avoid the problem of accidentally clearing a father that no longer points to the person being removed would be to just check if the father field is still pointing to that person. The setter method would still be in the list and would still be called, but it wouldn’t do any damage.



Source: stackoverflow