public abstract class EField extends EMessageObject implements java.io.Serializable
EField
. This allows instances of
the application class to be serialized to a
ByteBuffer
. The application class must also
define public static Builder builder()
and the
Builder
inner class. See
Note: EField
subclasses are limited
to 31 fields. This is due to eBus binary serialization format.
EMessageObject
shows how EMessage
and
EField
need to define a builder inner class used to
construct a subclass. But the example assumed that the
subclass was final
. This example shows how to define
builders for a non-final EField
class. The example
also applies to EMessage
. The following examples
show two classes: UserInfo
and its subclass
Employee
.
public class UserInfo
extends EField
{
public final String name;
public final int age;
private UserInfo(final Builder<?, ?> builder) {
super (builder);
this.name = builder.mName;
this.age = builder.mAge;
}
// builder code explained below.
}
public final class Employee
extends UserInfo
{
public final String department;
private Employee(final Builder builder) {
super (builder);
this.department = builder.mDepartment;
}
// builder code explained below.
}
Class UserInfo
can be instantiated on its own or as
Employee
superclass. Because of this UserInfo
is required to have two builder inner classes. The first is
an abstract builder which the Employee
builder
extends. The second is a concrete builder used to create
UserInfo
instances.
public static abstract class Builder<M extends UserInfo,
B extends Builder<M, ?>>
extends EField.Builder<M, B>
{
private String mName;
private int mAge;
// Protected constructor to allow subclass access.
protected Builder(final Class<? extends EMessageObject> targetClass) {
super (targetClass);
mAge = -1;
}
public B name(final String value) {
if (name == null || name.isEmpty()) {
throw (new IllegalArgumentException("value is null or empty"));
}
mName = value;
return ((B) this);
}
public B age(final int value) {
if (age < 0) {
throw (new IllegalArgumentException("value < zero"));
}
mAge = age;
return ((B) this);
}
@Override protected Validator validate(final Validate problems) {
return (super.validate(problems)
.requireNotNull(mName, "name")
.requireTrue(v -> (v ≥ 0), mAge, "age", Validator.NOT_SET);
}
// Since this class is abstract do not override buildImpl method.
}
Since Builder
is abstract it must use have the two
class parameters M
and B
which are then passed
to the superclass builder. Note that the setters use B
in the method signature so that the subclass type is returned
rather than UserInfo.Builder
. Method buildImpl
is not defined since that is only done in concrete builders.
UserInfo.ConcreteBuilder
extends
UserInfo.Builder
and defines buildImpl
. There
is nothing else for ConcreteBuilder
to do since the
setters and validation methods are provided by the superclass.
public static final class ConcreteBuilder
extends Builder<UserInfo, ConcreteBuilder>
{
private ConcreteBuilder() {
super (UserInfo.class);
}
@Override protected UserInfo buildImpl() {
return (new UserInfo(this));
}
}
UserInfo.builder
method returns a
UserInfo.ConcreteBuilder
instance since that class is
responsible for creating UserInfo
instances. But the
return type is the abstract UserInfo.Builder
.
public static Builder builder() {
return (new ConcreteBuilder());
}
Employee.Builder
is as you expect: it extends
UserInfo.Builder
, defines the department
setter method, validates the builder configuration, and
builds the Employee
instance.
public static final class Builder
extends UserInfo.Builder<Employee, Builder>
{
private String mDepartment;
private Builder() {
super (Employee.class);
}
public Builder department(final String value) {
if (value == null || value.isEmpty()) {
throw (new IllegalArgumentException("value is null or empty"));
}
mDepartment = value;
return (this);
}
@Override protected Validator validate(final Validator problems) {
return (super.validate(problems)
.requireNotNull(mDepartment, department));
}
@Override protected Employee buildImpl() {
return (new Employee(this));
}
}
EMessageObject
,
EMessage
,
Serialized FormModifier and Type | Class and Description |
---|---|
static class |
EField.Builder<M extends EField>
Used to create a new
EField instance. |
Modifier | Constructor and Description |
---|---|
protected |
EField(EField.Builder<?> builder)
Initiate field based on builder settings.
|
protected EField(EField.Builder<?> builder)
builder
- eBus message field builder.Copyright © 2001 - 2024. Charles W. Rapp. All rights reserved.