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 Person
s 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?
Advertisement
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.