How to overlay a superclass method using a polymorphic parameter?

Asked

Viewed 232 times

5

I have an abstract superclass Service with an abstract method onExecute(ServiceData data) that is superimposed in the subclass EchoService. However, in this overlaid method, I need the parameter to be a subclass of ServiceData. When trying to do this, Java says that I did not override the superclass method. From what I remember when I studied object-oriented programming I learned that a subclass can be passed where a superclass is expected. I don’t understand why it didn’t work.

These are my classes:

public abstract class ServiceData { /*...*/ }
public class EchoData extends ServiceData { /*...*/ }

public abstract class Service {
  protected abstract ServiceResponse onExecute(ServiceData data) throws Exception;
}

public class EchoService extends Service {
  @Override
  protected ServiceResponse onExecute(EchoData data) throws Exception {
    return null;
  }
}

The mistake:

Class 'Echoservice' must either be declared Abstract or implement Abstract method 'onExecute(Servicedata)' in 'Stilingueservice'

3 answers

7


Directly so there is no way because the language does not make automatic covariance. You can do this with Generics. I’m going to put a code here roughly, it doesn’t mean that it’s exactly like this (I know how to do it in C#, not in Java, but it should be very similar):

public abstract class ServiceData { /*...*/ }
public class EchoData extends ServiceData { /*...*/ }
public abstract class Service<T extends ServiceData> {
      protected abstract ServiceResponse onExecute(T data) throws Exception;
}
public class EchoService extends Service<EchoData> {
    @Override
    protected ServiceResponse onExecute(EchoData data) throws Exception {
        return null;
    }
}

I put in the Github for future reference.

I assume that EchoData derives from ServiceData.

  • Your solution worked perfectly! Thank you very much once again!

1

I just did a POC following what @alandplm suggested in the reply, changing the object Echodata for Servicedata and running a methods that has been implemented in Echodata.

To be able to execute this method, I assumed it existed by casting.

Stayed like this:

public class EchoData extends ServiceData {
        public EchoData() {
            super();
        }

        public void teste() {
            System.out.println("teste");
        }
    }

@Override
    protected ServiceResponse onExecute(ServiceData data) throws Exception {
        ((EchoData) data).teste();
        return null;
    }

Main test:

   public static void main(String[] args) throws Exception {

            EchoData echoData = new EchoData() ;
            EchoService teste = new EchoService();
            teste.onExecute(echoData);
        }

Console output:

teste

This above solution will compile, even if an object of the Servicedata type is passed. I do not advise the use because it is a gap in the code, even compiling. However, it shows that this implementation is possible!

I hope I’ve helped.

  • 1

    Now passes a ServiceData other than a EchoData. The first test you do is the one that doesn’t work right.

  • Yes, then we will have a Classcastexception. In this POC I tested I assumed the risk of not having the method. But you are right, there is error in execution time!

  • It really works, but the bad thing about this solution is that classes will have to be doing Sts all the time.

  • Yes... It is not the best solution (no doubt), but the study character is interesting. There are issues for certification that are like this. The code compiles and is asked what will happen if a Servicedata class is passed as parameter.

0

In protected ServiceResponse onExecute(EchoData data) throws Exception you need to make the parameter Data of the kind ServiceData. This will not interfere with the use, since when using the method you can pass an object of type EchoData no problem.

This issue is addressed in the Java specification in Section 8.4.8.3. The understanding of the Liskov principle and the functioning of Covariant Return Types and Contravariant Parameter Types.

  • But in the method onExecute(EchoData data) of EchoService I need to call a method that exists in EchoData but does not exist in ServiceData. This is precisely the problem

Browser other questions tagged

You are not signed in. Login or sign up in order to post.