Is there any way of using Records with inheritance?
Asked Answered
B

2

64

I have a bunch of @Data classes using Lombok and I want to migrate all of them to use the new Record functionality available in Java 14.

I know it's a little bit earlier but this is an experimental test that I'm doing.

The main problem here is involving inheritance. I have a class B which extends a class A. Is there any way of using Records with inheritance?

Beersheba answered 26/8, 2020 at 21:11 Comment(0)
R
76

The JEP states this:

Restrictions on records

Records cannot extend any other class, and cannot declare instance fields other than the private final fields which correspond to components of the state description. Any other fields which are declared must be static. These restrictions ensure that the state description alone defines the representation.

The Java 17 JLS 8.10 notes1 this:

A record declaration does not have an extends clause, so it is not possible to explicitly declare a direct superclass type, even Record.

However, a record can implement interfaces, so you can use them polymorphically. Furthermore, since records will inherit any default methods in the interfaces that they implement, they do support a limited form of inheritance.


1 - This is a non-normative statement, but it is obviously true since the specified syntax for RecordDeclaration clearly does not allow extends to be used.

Rightly answered 27/8, 2020 at 13:10 Comment(1)
Inheriting an interface that has default methods sounds really flexible/powerful ... I'm about to try it out ...Nonperformance
T
42

Is there any way of using records with inheritance?

Records already extend java.lang.Record. As Java does not allow multiple inheritance, records cannot extend any other class.

Consider, for example, the following record Point:

public record Point(double x, double y) {}

You can compile it using:

javac --enable-preview -source 14 Point.java

With the help of javap, you can can have details about the code generate for Point:

javap -p Point

The output will be:

Compiled from "Point.java"
public final class Point extends java.lang.Record {
  private final double x;
  private final double y;
  public Point(double, double);
  public java.lang.String toString();
  public final int hashCode();
  public final boolean equals(java.lang.Object);
  public double x();
  public double y();
}
Trainload answered 27/8, 2020 at 12:0 Comment(3)
If record Derived extends record Base and Base extends java.lang.Record, then Derived transitively extends Record. There is no need for multiple inheritance and this is just poor language design, which might hopefully be resolved at some point in the future.Altdorfer
This answer is absolutely wrong. The only reason why records can't be inherited is because they are final by design. Furthermore, every single class (not record) in Java extends java.lang.Object.... and you can still have your own classes extend another.Gautious
@Altdorfer - The JEP states that it is a requirement that the field declarations for a record be the complete state description. Inheriting instance fields or instance methods from a superclass (other than Object) would break this. The extends restriction is NOT "poor design" or "an oversight". It is necessary for one of the motivating use-cases for record.Rightly

© 2022 - 2024 — McMap. All rights reserved.