81355

Inheritance and Multiple Collaborators

Question:

I have several Java interfaces/ABCs/classes:

public abstract class Target { public abstract void fire(Load load); } public class HttpTarget extends Target { @Override public void fire(Load load) { // ... } } public interface Load { // ... } public class HttpLoad implements Load { // ... } // Inside a driver Target target = testSuite.getTarget(); Load load = testSuite.getLoad(); target.fire(load);

So essentially a Target can fire() a Load. My main app Driver doesn't care about what kind of Target is returned by getTarget(), or what kind of Load is returned by getLoad(). It's job is to make sure that a load is fired.

I'd like to change the fire() method definition inside HttpTarget to:

@Override public void fire(HttpLoad httpLoad) { // ... }

However when I do that, Java complains that the method override doesn't match the definition provided by its parent Target class (as Load and HttpLoad are two different things).

What's the solution here? Generics? Abstract factories? <strong>Ultimately, I want to be able to enforce that HttpTarget's fire() method can only accept HttpLoads, but still be compatible with the Driver code.</strong> Can someone provide a code example? Thanks in advance!

Answer1:

Yes, you would need generics:

public abstract class Target<L extends Load> { public abstract void fire(L load); } public class HttpTarget extends Target<HttpLoad> { @Override public void fire(HttpLoad load) { ... } } public interface TestSuite<L extends Load> { // or class L getLoad(); Target<L> getTarget(); } public class HttpTestSuite implements TestSuite<HttpLoad> { @Override public HttpLoad getLoad() { ... } @Override public Target<HttpLoad> getTarget() { return new HttpTarget(); } }

The reason Java refuses to compile your HttpTarget class is because it doesn't override the Target's fire(Load) method. Indeed, a Target, by contract is supposed to accept any kind of Load as argument. And the HttpTarget's fire() method only accepts instances of HttpLoad, and thus breaks the Liskov principle. Generics are the solution to this problem.

Answer2:

You will have to use generics and even then it is not exactly what you want.

public interface Load<T extends Load> { public void someMethod(); } public class HttpLoad implements Load<HttpLoad> { @Override public void someMethod() { System.out.println("Http Load"); ... } } public abstract class Target<T extends Load> { public abstract void fire(Load<T> load); } public class HttpTarget extends Target<HttpLoad> { @Override public void fire(Load<HttpLoad> load) { load.someMethod(); } }

Now if you write

Target<HttpLoad> httpTarget = new HttpTarget(); Load<HttpLoad> httpLoad = new HttpLoad(); Load<OtherLoad> otherLoad = new OtherLoad(); Load otherLoad2 = new OtherLoad(); httpTarget.fire(httpLoad); httpTarget.fire(otherLoad); // this doesn't compile httpTarget.fire(otherLoad2) // this how ever compiles

Recommend

  • how to read and edit existing pptx using Docx4j?
  • Doctrine ORM: use interface as relation for different entities?
  • How to use the resource module to measure the running time of a function?
  • Find VMID for running instance
  • SSL client cert authentication for only some URLs?
  • Spark (Scala) Writing (and reading) to local file system from driver
  • NHibernate manually control fetching
  • How do I get the list of bad records that didn't load in Bigquery?
  • pip in virtualenv gets ConnectTimeoutError
  • Clarification on min distance on LocationManager.requestLocationUpdates method, min Distance paramet
  • pyodbc doesn't report sql server error
  • how to find common suffix in java by using method
  • Display java JPanel in a JFrame
  • C: Incompatible pointer type initializing
  • jQuery ready not fired after rails link_to is clicked
  • Caching attributes in superclass
  • Sencha Touch 2.0 Controller refs attribute not working?
  • Could not find rake using whenever rails
  • Android full screen on only one activity?
  • Yii2: Config params vs. const/define
  • $wpdb not working in file of WordPress plugin
  • Is it possible to access block's scope in method?
  • why overloaded new operator is calling constructor even I am using malloc inside overloading functio
  • how to adjust image in a panel in Java swing?
  • Ajax Loaded meta Tags
  • Q promise. Difference between .when and .then
  • SignalR .NET Client Invoke throws an exception
  • Why value captured by reference in lambda is broken? [duplicate]
  • What is Eclipse's Declaration View used for?
  • Possible to stop flickering java tooltip in heavyweight mode?
  • output of program is not same as passed argument
  • 'TypeError' while using NSGA2 to solve Multi-objective prob. from pyopt-sparse in OpenMDAO
  • Redux, normalised entities and lodash merge
  • what is the difference between the asp.net mvc application and asp.net web application
  • Akka Routing: Reply's send to router ends up as dead letters
  • Is there a mandatory requirement to switch app.yaml?
  • KeystoneJS: Relationships in Admin UI not updating
  • WPF Applying a trigger on binding failure
  • unknown Exception android
  • Checking variable from a different class in C#