Struct Embedding in Java
Java supports composition through nested classes and interfaces, which can be used to express a more seamless composition of types. This is somewhat similar to struct embedding in other languages.
import java.util.function.Supplier;
class Base {
int num;
Base(int num) {
this.num = num;
}
String describe() {
return String.format("base with num=%d", num);
}
}
class Container {
private Base base;
String str;
Container(Base base, String str) {
this.base = base;
this.str = str;
}
// Delegate method to access base's num
int getNum() {
return base.num;
}
// Delegate method to access base's describe
String describe() {
return base.describe();
}
}
public class StructEmbedding {
public static void main(String[] args) {
// When creating objects, we need to initialize the composed object explicitly
Container co = new Container(new Base(1), "some name");
// We can access the base's fields through getter methods on Container
System.out.printf("co={num: %d, str: %s}%n", co.getNum(), co.str);
// We can also access the full path using the getter method
System.out.println("also num: " + co.getNum());
// We can invoke a method that was delegated from Base directly on co
System.out.println("describe: " + co.describe());
// In Java, we can use interfaces to achieve a similar effect to embedding
Supplier<String> describer = co::describe;
System.out.println("describer: " + describer.get());
}
}
To run the program:
$ javac StructEmbedding.java
$ java StructEmbedding
co={num: 1, str: some name}
also num: 1
describe: base with num=1
describer: base with num=1
In this Java example, we’ve simulated struct embedding using composition and delegation. The Container
class contains a Base
object and delegates some methods to it. This achieves a similar effect to struct embedding in other languages.
We’ve also used a functional interface (Supplier
) to demonstrate how Java can achieve a similar effect to interface implementation through embedding. The Container
object can be used wherever a Supplier<String>
is expected, as long as we’re referring to its describe
method.
While Java doesn’t have direct struct embedding, these techniques of composition, delegation, and interfaces can often achieve similar goals of code reuse and type relationships.