Given 3 java classes, Container
extends Box
and Box
extends Dimension
and I am trying to port them in Elixir
and it is extremly counterintuitive.
# https://github.com/skjolber/3d-bin-container-packing/blob/master/src/main/java/com/github/skjolberg/packing/Box.java
public class Dimension {
protected int width; // x
protected int depth; // y
protected int height; // z
protected long volume;
protected final String name;
public Dimension() {
this(null);
}
public Dimension(String name, int w, int d, int h) {
this.name = name;
this.depth = d;
this.width = w;
this.height = h;
calculateVolume();
}
protected void calculateVolume() {
this.volume = ((long)depth) * ((long)width) * ((long)height);
}
}
# https://github.com/skjolber/3d-bin-container-packing/blob/master/src/main/java/com/github/skjolberg/packing/Dimension.java
public class Box extends Dimension {
final int weight;
public Box(int w, int d, int h, int weight) {
super(w, d, h);
this.weight = weight;
}
}
# https://github.com/skjolber/3d-bin-container-packing/blob/master/src/main/java/com/github/skjolberg/packing/Container.java
public class Container extends Box {
private int stackWeight = 0;
private int stackHeight = 0;
private ArrayList<Level> levels = new ArrayList<>();
public Container(Container container) {
super(container.getName(), container.getWidth(), container.getDepth(), container.getHeight(), container.getWeight());
}
}
And I am heading to this direction
defmodule Foo.Dimension do
alias Foo.{Box, Dimension}
defstruct [:name, :width, :depth, :height, :volume]
defmacro __using__(_opts) do
quote do
@spec calculate_volume(%Dimension{}) :: %Dimension{}
def calculate_volume(%Dimension{} = dimension) do
volume = dimension.depth * dimension.width * dimension.height
%{dimension | volume: volume}
end
....
end
end
end
defmodule Foo.Box do
use Foo.Dimension
alias Foo.{Box, Dimension}
@enforce_keys [:weight]
defstruct [:name, :weight, :width, :depth, :height, :volume]
end
defmodule Foo.Container do
use Foo.Dimension
alias Foo.{Container, Dimension}
defstruct [:volume, stack_weight: 0, stack_height: 0, width: 0, depth: 0, height: 0, weight: 0...]
end
The problems I am having are:
- I have to repeat the base struct
[:name, :width, :depth, :height, :volume]
from Dimension all the way up to the top extender(Container) - What is the best way to deal with the
Dimension
constructor that callscalculateVolume()
? If extender(Box
orContainer
) do asuper()
call, how does it initiate:volume
? Do I have to
%Container{...} |> Container.calculate_volume()
%Box{...} |> Box.calculate_volume()
- I am not sure if it is a good idea to mimic the inheritance like that in
Foo.Dimension
by usingdefmacro __using__(_) do