Sinobu

Concept

In the context of Java programming, a 'property' generally refers to the characteristics or attributes of a class or object. These properties define the state of an object and encapsulate the data associated with it. In Java, properties are typically represented as private fields within a class, with corresponding getter and setter methods to access and modify their values.

Here's an example of a Java class with properties:

class Person {
    private String name; // Property: name

    private int age; // Property: age

    // Constructor
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // Getter method for name property
    public String getName() {
        return name;
    }

    // Setter method for name property
    public void setName(String name) {
        this.name = name;
    }

    // Getter method for age property
    public int getAge() {
        return age;
    }

    // Setter method for age property
    public void setAge(int age) {
        this.age = age;
    }
}

In this example, the Person class has two properties: name and age. These properties are declared as private fields within the class to encapsulate their implementation details and prevent direct access from outside the class. Getter and setter methods (getName(), setName(), getAge(), setAge()) are provided to allow controlled access to these properties.

Using properties in Java classes promotes encapsulation, which is one of the fundamental principles of object-oriented programming (OOP). Encapsulation hides the internal state of an object and exposes only the necessary interfaces for interacting with it, improving code maintainability, reusability, and flexibility.

Models

In Sinobu, model is a set of properties. If a class you define has properties, it is already a model.

Models can be retrieved from a class using the kiss.Model#of(Class) method, but there should not be many situations where the end user needs to retrieve the model directly.

Model model = Model.of(Person.class);

Property

In Sinobu, a property refers to a value accessible by name and defined by a field or method. Property name is arbitrary.

By Field

Property definition by field.

public String filedProperty = "This is property";

With the final modifier, the value cannot be changed and is therefore not treated as a property.

public final String finalField = "This is NOT property";

Access modifiers other than public are not treated as properties.

protected String nonPublicField = "This is NOT property";

If you want to treat fields with access modifiers other than public as properties, use the Managed annotation.

@Managed
protected String managedField = "This is property";

By Variable Field

Property definition by Variable field.

public Variable<String> variableField = Variable.of("This is property");

Unlike normal fields, they are treated as properties even if they have final modifier.

public final Variable<String> finalField = Variable.of("This is property");

Access modifiers other than public are not treated as properties.

protected Variable<String> nonPublicField = Variable.of("This is NOT property");

If you want to treat fields with access modifiers other than public as properties, use the Managed annotation.

@Managed
protected Variable<String> managedField = Variable.of("This is property");

By Method

Property definition by method. The getter and setter methods must be defined according to the Java Bean naming conventions.

class GetterAndSetter {
    private String property = "This is property";

    public String getProperty() {
        return property;
    }

    public void setProperty(String property) {
        this.property = property;
    }
}

The getter and setter methods do not need to have a public modifier.

class NonPublicGetterAndSetter {
    private String property = "This is property";

    String getProperty() {
        return property;
    }

    void setProperty(String property) {
        this.property = property;
    }
}

Manipulation

Normally, end users do not use Model API to manipulate or traverse properties. The following is mainly required for framework and library production.

Models and properties can be used to get, set and monitor property values.

Get

Get the value by name.

public void getProperty() {
    Person person = new Person();
    person.setAge(1);

    Model model = Model.of(Person.class);
    Property property = model.property("age");

    assert model.get(person, property).equals(1);
}

Set

Set the value by name.

public void setProperty() {
    Person person = new Person();
    Model model = Model.of(Person.class);
    Property property = model.property("age");

    // assign property value
    model.set(person, property, 1);

    assert 1 == person.getAge();
}

If you set a property value, it is recommended that you reassign the return value to the object. This is necessary because the Record is immutable.

public void setAtRecord() {
    Point point = new Point(0, 0);
    Model<Point> model = Model.of(Point.class);
    point = model.set(point, model.property("x"), 10);
    assert point.x == 10;
    point = model.set(point, model.property("y"), 20d);
    assert point.y == 20d;
}

Monitor

Monitor the Variable value.

public void observeVariableProperty() {
    class Item {
        public Variable<Integer> count = Variable.of(0);
    }

    Item item = new Item();
    Model model = Model.of(Item.class);
    List<Integer> values = model.observe(item, model.property("count")).toList();
    assert values.isEmpty();

    item.count.set(1);
    item.count.set(2);
    item.count.set(3);
    assert values.get(0) == 1;
    assert values.get(1) == 2;
    assert values.get(2) == 3;
}
Dependency InjectionExtensibility