FasterXML / java-classmate

Library for introspecting generic type information of types, member/static methods, fields. Especially useful for POJO/Bean introspection.
http://fasterxml.com
Apache License 2.0
258 stars 42 forks source link

Private methods handled as virtual for inherting classes #36

Open meszibalu opened 7 years ago

meszibalu commented 7 years ago

I am using classmate-1.3.3 and I faced with an issue when using MemberResolver. The problem is that if a class and its child class have exactly the same private methods then I cannot access to super class' private method. This behavior is fine when these methods are at least package-private, but private methods do not override each other.

For demonstrating the issue I have attached a simple unit test. In testPrivate() test members.getMemberMethods() should return two functions in my opinion.

InheritanceTest.txt

Best regards, Balazs

cowtowncoder commented 7 years ago

@meszibalu Thank you for reporting this. It may take a while for me to look into this but just adding a note to mention I saw this.

I am not 100% sure I understand problem from description, but I assume reproduction explains it.

cowtowncoder commented 7 years ago

Hmmh. I don't think I agree here -- I don't see why both private methods should be reported. What would be use case for doing that? If you want to see private method from parent class, you should probably resolve that (and/or there should be a way to traverse override hierarchy).

It is possible I am missing a use case here so would appreciate help.

meszibalu commented 6 years ago

Because private methods do not override each other. Let me give you another example:

public class A {
  private void a() {}
  private void x() {}
}
public class B extends A {
  private void b() {}
  private void x() {}
}

If I resolve B with MemberResolver, then it will return 3 methods. But why 3? B.x does not override A.x, because private methods are not virtual. In my opinion if we return A.a when resolving B, then we should also return A.x, not only B.x.

cowtowncoder commented 6 years ago

But there is no real way to call masked base class variant. Except perhaps reflection does allow that. I do see that call dispatching is different from overriding case (which is bit surprising actually) so you are right regarding actual JVM operation.

So I guess my question is really: what is the use case for this?

The reason for my hesitation is that up until this point, uniqueness of signatures (name + arguments + return type) is guaranteed, and conceptually adding both private methods would complicate this part.

meszibalu commented 6 years ago

Yes, you are right, reflection allows that, because they are not virtual. For virtual methods, nobody can call the super method.

A possible use case for this: Let's assume that there some beans and bean inheritance is permitted. There are also some lifecycle events like @PostConstruct or @PreDestroy. In this case, we have to name those methods differently, like initializeParentClass(), initializeChildClass(), etc.

I understand your concern, it is quite tricky to handle, and there is a workaround for that if we resolv the members of the base class, so this argument is a little bit theoretical :). This issue also exists for private fields. If you have two private fields with the same name in an inheritance hierarchy, MemberResolver will shadow the field of the parent implementation.