Java Compilation Error with Method overloading - java

What would be the best way to achieve testCall2 below without doing explicit parsing (Sub1) in?
class Super {
}
class Sub1 extends Super {
}
class Sub2 extends Super {
}
public void testCall2(Super in) {
testCall(in); // <~~~ Compilation Error
}
public void testCall(Sub1 sub) {
}
public void testCall(Sub2 sub) {
}

You'd have to refactor and use polymorphism. Declare the testCall method in Super
class Super {
public void testCall() {}
}
and implement it in the subclasses.
Then invoke it
public void testCall2(Super in) {
in.testCall();
}
Otherwise you'll have to use a cast to transform the value's type to a type expected by either of the methods.

Obviously it will give compile time error because you are creating methods out of class body. your all methods are out of class body..
class Super {
}
class Sub1 extends Super {
}
class Sub2 extends Super {
}// your all three classes are started and ended immediately
public void testCall2(Super in) {
testCall(in); // <~~~ Compilation Error
}
public void testCall(Sub1 sub) {
}
public void testCall(Sub2 sub) {
}
//and all three methods are defined out of any class body.

Related

Definition of abstract method accepting type of implementing class only

Objective: Define an abstract method which accepts a reference of type (or sub-type) of the implementing class.
What I came up with is:
public abstract class Parent<T extends Parent> {
public abstract void foo(T t);
}
An implementation could be:
public class Child extends Parent<Child> {
public void foo(Child child) { /* ... */ }
}
At first sight this looks like a satisfying solution, but it allows as well following implementation:
public class Child1 extends Parent<Child> {
public void foo (Child child) { /* ... */ }
}
Is there a way to define the abstract method to prevent the second implementation?
It is not totally possible to force that constraint in compilation time. However you can make it a bit more cumbersome to violate that constraint like so:
abstract class Parent<T extends Parent> {
protected Parent(Class<T> clazz) {
if (!this.getClass().equals(clazz)) {
throw new IllegalArgumentException("you must pass this; invalid attempt to extend Parent where subclass does not assign T to itself.
}
}
// ...
}
class GoodChild extends Parent<GoodChild> {
public GoodChild() { super(GoodChild.class) };
}
class BadChild extends Parent<GoodChild> {
public BadChild() { super(BadChild.class) }; // cannot compile.
}
class WorstChild extends Parent<GoodChild> {
public WorstChild() { super(GoodChild.class); } // compiles but will fail in run-time.
}
class CircularChild extends Parent<Parent> {
public CircularChild() { super(Parent.class); } // compiles but will fail
}
The trick is that the parent constructor code is binding in run-time the this's class to be the same class as T that is what you want.

Abstract callback in reflection method of java

I have a class in jar of which I want to invoke a method. But that method has parameter of abstract class and that abstract class is inner method of class in jar. AbstractClassA is a HIDDEN class. Here is code:
public class A{
private invokeThisMethod(AbstractClassA object){
}
public abstract class AbstractClassA {
public void update(int remaining){}
}
}
public class myClass{
//using Reflection get object of class A
objectOfClassAusingReflection.inovke("invokeThisMethod", params)
}
Problem here is how do I create concrete implementation of AbstractClassA to pass in invoke method and get update method callbacks ?
Something like this should work:
AbstractClassA a = new AbstractClassA() {
public void update(int remaining) {... do something...}
};
objectOfClassAusingReflection.inovke("invokeThisMethod", a);
You cannot create an instance of abstract class or any interface at runtime.
Instead create an anonymous class for this.
public abstract class A {
public void fun(){....}
public abstract void absFun();
}
public class MyClass {
objectOfClassA = new A(){
public void absFun(){...}
}
}
Or you can first create implementation for that abstract classes for which you will have to create another class extending A
class AWrapper extends A {
public class ImplementationClassA extends AbstractClassA {
// override abstract functions...
}
}
Now you can use this Awrapper class
AWrapper wrapperObj = new AWrapper();
A obj = wrapperObj; // just to make it clear that A can hold wrapperObj as it is implementation of it.
A.AbstractClassA absObj = wrapperObj.new ImplementationClassA();
...
objectOfClassAusingReflection.inovke("invokeThisMethod", params)
Below code should work--
Here, i used anonymus classes for both outer and inner class and then with the help of getdeclatedMethod called your update method.
"TestAbs" is your jar class--
public abstract class TestAbs {
private void invokeThisMethod(AbstractClassA object) {
}
public abstract class AbstractClassA {
public void update(int remaining) {
}
}
}
Then calling your jar class from "TestAbs1" like below--
public class TestAbs1 {
public static void main(String[] args) {
TestAbs.AbstractClassA abs = new TestAbs() {
AbstractClassA a = new AbstractClassA() {
public void update(int remaining) {
System.out.println("Inside update method : " + remaining);
}
};
}.a;
try {
int i = 1;
Class<?> class1 = Class.forName("app.test.mytest.TestAbs$AbstractClassA"); -- (*Getting instance of inner class*)
System.out.println(class1.getDeclaredMethod("update", int.class));
class1.getDeclaredMethod("update", int.class).invoke(abs, i);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
The output i got is --
public void app.test.mytest.TestAbs$AbstractClassA.update(int)
Inside update method : 1
Answer to your Comment:-
What I understood from your comment is that, you wanted to call method from abstractClass which is hidden in outerclass.
As per my understanding, there is one way like below--
public abstract class TestAbs {
private void invokeThisMethod(AbstractClassA object) {
}
private abstract class AbstractClassA { --- your hidden class
public void update(int remaining) {
}
}
public class ImplementedClass extends AbstractClassA{ -- use implemented class here
....
...
}
}
And after that, use your ImplementedClass the same way mentioned above.
You can find reference example for private inner class here from java docs.
Note: In your question context, since your inner class and outer class is in jar, so I think it is difficult for you add implementation class in your jar.
In case, you find any alternatives, please let all knows about this;
thanks.

Calling a method of sub-sub-class

I am having issue with calling a method of a class at the 2nd level of inheritance from the super class.
The scenario is this,
abstract class SuperClass
{
public void MethodOne()
{
MethodTwo();
}
public abstract void MethodTwo();
}
class Sub1 extends SuperClass
{
public void MethodTwo()
{
//code in sub1
}
}
class Sub2 extends SuperClass
{
public void MethodTwo()
{
//code in sub2
}
}
With the below code I expect the MethodTwo() from the Sub2 to be called. But the method from Sub1 is getting called. Am I missing something?
SuperClass anObj = new Sub2();
anObj.MethodOne();
I have combined all of your classes as inner-classes to help me test them. You can remove the "static" keyword from the classes if you put them in different files:
public class Example {
abstract static class SuperClass
{
public void MethodOne()
{
MethodTwo();
}
public abstract void MethodTwo();
}
static class Sub1 extends SuperClass
{
#Override
public void MethodTwo()
{
System.out.println("Sub1.MethodTwo()");
}
}
static class Sub2 extends SuperClass
{
#Override
public void MethodTwo()
{
System.out.println("Sub2.MethodTwo()");
}
}
public static void main(String[] args) {
SuperClass anObj = new Sub2();
anObj.MethodOne();
}
}
When I run this class it outputs Sub2.MethodTwo(), proving that it does actually work as you expect.
I notice the code you provided is not proper java code, and does not compile. That's because you've marked methods both as abstract and then provided an implementation with curly-braces { ... }.
I assume this is an example of a setup that isn't working for you? If so, I think it doesn't represent your case properly - as it's working as one would expect!
First, you lack the actual implementation of method2.
You should not be able to call an abstract method.
You need to override the abstract in the subclass.
class Sub1 extends SuperClass
{
#override
public void MethodTwo()
{
//code in sub1
}
}
class Sub2 extends SuperClass
{
#override
public void MethodTwo()
{
//code in sub2
}
}
This might fix your problem.

How do I unit test overridden methods which call super?

http://stackoverflow.com/questions/6645263/unit-testing-overridden-methods-which-call-super (This question has similar wording but is not the same)
I have something along the lines of:
public class SuperClass {
private int superClassInteger = 2;
public void superClassMethod() {
superClassInteger = 5;
}
public int getSuperClassInteger() {
return superClassInteger();
}
}
Then in my test I have:
public class SuperClassTest {
public void testSuperClassMethod() {
SuperClass superClass = new SuperClass();
superClass.superClassMethod();
assertEquals(5, super.getSuperClassInteger())
}
}
I then have a subclass:
public class SubClass {
private int subClassInteger = 2;
public void subClassMethod() {
super.superClassMethod();
subClassInteger = 32;
}
public int getSuperClassInteger() {
subClassInteger;
}
}
Then my test for the subclass:
public class SubClassTest {
public void testSubClassMethod() {
SubClass subClass = new SubClass();
subClass.subClassMethod();
assertEquals(5, subclass.getSuperClassInteger());
assertEquals(32, subclass.getSubClassInteger())
}
}
My problem is that to test the behavior of the subclass, I am repeating the test code I have for the super class. I could take out: assertEquals(5, subclass.getSuperClassInteger()); as I just want to test the business logic of the subclass. However, the problem with this is that if somebody accidentally removes the call to superClassMethod the test will still pass. So I need verify that a call to super is made. What is a common way of testing this use case?
Note: I know composition / strategy pattern vs inheritance helps solve this problem but for that to be the solution you are basically saying that I should NEVER override a method and invoke super in my code (which I find hard to believe there will never be a use for)
Use mockito spies. You can check for nearly any method call using that testing Framework.
https://github.com/mockito/mockito
This is probably not the answer you want (i.e not a workaround), but the answer you deserve but you should never override a method and invoke super.
I'm working on a legacy project that does that a lot, it's a nightmare to maintain, to debug and to test.
Instead, it's better to use an abstract class with a template method pattern:
Before
public class SuperClass<T> {
public void include(T t) {
validate(T);
dao.save(T);
}
// I've found code like that.
public void validate(T t) {
}
}
public class SubClass1 extends SuperClass<MyClass> {
#Override
public void include(MyClass mc) {
doStuff(mc);
doMoreStuff(mc);
super.include(mc);
}
#Override
public void validate(MyClass mc) {
doValidationStuff();
}
}
public class SubClass2 extends SuperClass<AnotherClass> {
#Override
public void include(AnotherClass ac) {
doDifferentStuff();
super.include(mc);
}
}
After
public abstract class AbstractClass<T> {
abstract void validate(T t);
// this method can now be tested
public void include(T t) {
validate(T);
dao.save(T);
}
}
public class Class1 extends AbstractClass<MyClass> {
public void validate(MyClass mc) {
doValidationStuff();
doStuff(mc);
doMoreStuff(mc);
}
}
public class Class2 extends AbstractClass<AnotherClass> {
public void validate(AnotherClass ac) {
doDifferentStuff();
}
}
As you can see, this refactoring simplifies maintenance and testing, you don't have to worry about having to mock the superclass method call in the Class1 and Class2 tests, and the code is closed to modification and open to extension, i.e, more maintainable.
Use JMockit and check the call to super with a Verification.
JMockit
Example for this
public void test {
SubClass subClass = new SubClass();
subClass.subClassMethod();
new Verifications() {
// mock only this method of superClass - and only in this test
#Mocked (methods = "superClassMethod")
SuperClass superClass;
{
superClass.superClassMethod();
times = 1; // specify invocation count
}
};
}

How to infer subtype in supertype

Say you have a super-class. In that super class you want to pass runtime object of itself (this) as a parameter to an overloaded method. Trick is, this overloaded method is overloaded by sub-class type. When you try to do it, you'll get a
method ... is not applicable(actual argument
... cannot be converted to ... by method invocation
conversion)
Instead you would need to implement the method separately in each subtype (just to get the correct runtime class), which is a lot of duplicate effort when the contents of the method are identical.
e.g:
public class InferTypeTest {
public static void main(String[] args) {
SubClass1 s1 = new SubClass1();
s1.sayHi();
}
public static void sayHi(SubClass1 clz) {
System.out.println("clz 1");
}
private abstract static class SuperClass{
public void sayHi() {
InferTypeTest.sayHi(this);
}
}
private static class SubClass1 extends SuperClass{
}
}
Yes, this is how double dispatch works, you have to override the accept method in each subclass like this:
private static abstract class NodeWithChildren implements DomNode {
/* snip */
public void accept(DomNodeVisitor visitor) {
for (DomNode child : children) {
child.accept(visitor);
}
}
}
private static class BodyNode extends NodeWithChildren {
public void accept(DomNodeVisitor visitor) {
visitor.visit(this);
super.accept(visitor);
visitor.visited(this);
}
}
private static class DivNode extends NodeWithChildren {
public void accept(DomNodeVisitor visitor) {
visitor.visit(this);
super.accept(visitor);
visitor.visited(this);
}
}
}
BodyNode is a NodeWithChildren
DivNode is a NodeWithChidren
NodeWithChildren is a DomNode
DomPrinterVisitor is a DomNodeVisitor
DomNodeVisitor's visitor can visit "BodyNode" or "DivNode, But you are passing "NodeWithChildren" to visit.
Here BodyNode is a NodeWithChildren but NodeWithChildren is not BodyNode/
Theary is if B extends A, you can say B is a A/ not A is a B.

Categories