0

Suppose I have a class Thing and some function/method that accepts a thing myFunction(Thing x). I want to create a class Thing2 which can be passed into myFunction, and which replicates the interface of Thing by supporting all the same public methods and fields etc. One way to do this would be to have Thing2 be a subclass of Thing. But is there a way to have Thing2 be a subtype of Thing without making it a subclass — for example, if I don't want Thing2 to inherit private fields of Thing?

And if it is not possible using regular Java, is it possible to do so by generating Java bytecode via some other means?

I am asking this question purely out of curiosity, I don't actually have a specific problem that I am trying to solve.

Adrian
  • 14,931
  • 9
  • 45
  • 70
  • 7
    It sounds like you should really have an interface to implement... – Jon Skeet Aug 17 '23 at 18:46
  • @JonSkeet Of course, I agree that that would be better for real-world code. I am simply asking because I am curious about whether the JVM implementation details would allow this. – Adrian Aug 17 '23 at 18:48
  • 2
    *"if I don't want `Thing2` to inherit private fields of `Thing`?"* how does a subclass in inherit private fields? Am I missing something? – Grinding For Reputation Aug 17 '23 at 18:49
  • If Java class "Thing2" inherits from super class "Thing2" ... then Thing2 *IS* a subclass. Period. Full stop. ALTERNATIVES: Yes, you can generate bytecode on the fly:. For example: https://stackoverflow.com/questions/52867815/. Better, it sounds like you simply want an "interface": https://docs.oracle.com/javase/tutorial/java/concepts/interface.html – paulsm4 Aug 17 '23 at 18:56
  • 2
    *"for example, if I don't want Thing2 to inherit private fields of Thing?"* Lousy example, since private members are not inherited anyway. – Old Dog Programmer Aug 17 '23 at 19:17
  • If you don't use inheritance then you won't be able to pass _Thing2_ to _myFunction_. Possibly add an example of what you're trying to achieve. – Reilas Aug 17 '23 at 21:45
  • 1
    First, if `Thing` is a class and you pass to your method an object that is not a `Thing` or a subclass of `Thing`, then you are getting a compile-time error. No way to avoid that. Second, it hardly applies to your imagined situation, but there are two cases where a subtype of a class type is not a subclass: (1) E.g., `ArrayList extends Integer>` is a subtype of `ArrayList extends Number>` but is still the same class, not a subclass. Wildcards in generics allow many such cases. (2) The type of `null` is a subtype of any type, so also a subtype of `Thing`. So yes, pass `null` . – Ole V.V. Aug 17 '23 at 23:06

1 Answers1

3

This is exactly what the D in SOLID is talking about. The D stands for Dependency inversion, and it can be phrased as: "Abstractions should not depend on concrete implementations".

What you have is a function that takes a Thing. A concrete class. But what you really want is a function that takes "anything that happens to support my frobnicate() method". That means the function has the wrong signature. If the function only requires a specific interface, then you want an interface in Java. Rather than

public class Thing {
  private Foo lotsOfImplementationDetails;

  public void frobnicate() {
    ...
  }
}

void myFunction(Thing x) {
  // All I want is frobnicate(), but I depend on the *whole* state.
  ...
}

consider

public interface Frobnicatable {
  public void frobnicate();
}

public class Thing implements Frobnicatable {
  private Foo lotsOfImplementationDetails;

  @Override
  public void frobnicate() {
    ...
  }
}

void myFunction(Frobnicatable x) {
  // Anything will work, provided it has the right method.
  ...
}
Silvio Mayolo
  • 62,821
  • 6
  • 74
  • 116
  • I agree with everything you said but this really doesn't answer my question. I am asking a conceptual question about the JVM out of curiosity, not asking about what kinds of design patterns are good for actual code which one might use. – Adrian Aug 17 '23 at 18:54
  • 1
    I see. I can't really prove a negative, but I'm not aware of a way to make an unrelated class `Thing2` masquerade as an instance of `Thing` on the JVM. All casts are checked at the VM level, so there's no equivalent to C++'s extremely unsafe `reinterpret_cast`. – Silvio Mayolo Aug 17 '23 at 18:55
  • @SilvioMayolo, _"frobnicate"_, where did you possibly find this word? – Reilas Aug 17 '23 at 21:49
  • 1
    @Relias One of my professors used it. It's my go-to word for "generic unnamed action", sort of my `foo` / `bar` but as a verb. – Silvio Mayolo Aug 17 '23 at 23:24