##### Get and Put Methods

Get and put methods are generated automatically for each of a class's public slots. These are 1-argument messages, named after the slots.

In the point class whose definition begins with

```     :- class point =
[public x:float=0,
public y:float=0].
```

the get and put methods are automatically generated for the `x` and `y` slots. If the class defines a `create/0` method, then the command

```     | ?- create(point, PointObj),
PointObj >>  x(OldX),
PointObj >>  y(OldY),
PointObj <<  x(3.14159),
PointObj <<  y(2.71828).
```

creates a point object and binds both `OldX` and `OldY` to 0.0E+00, its initial slot values. Then, it changes the values of the `x` and `y` slots to 3.14159 and 2.71828, respectively. The variable `PointObj` is bound to the point object.

It is possible, and sometimes quite useful, to create get and put methods for slots that do not exist. For example, it is possible to add a polar coordinate interface to the point class by defining get and put methods for `r` and `theta`, even though there are no `r` and `theta` slots. The get methods might be defined as follows:

```     Self >> r(R) :-
Self >> x(X),
Self >> y(Y),
R2 is X*X + Y*Y,
sqrt(R2, R).

Self >> theta(T) :-
Self >> x(X),
Self >> y(Y),
A is Y/X,
atan(A, T).
```

This assumes that `library(math)`, which defines the `sqrt/2` and `atan/2` predicates, has been loaded. The put methods are left as an exercise.

In the rational number class whose definition begins with

```     :- class rational =
[public num:integer,
public denom:integer].
```

get and put methods are automatically generated for the `num` and `denom` slots. It might be reasonable to add a get method for `float`, which would provide a floating point approximation to the rational in response to that get message. This is left as an exercise.

It is also possible to define get and put methods that take more than one argument. For example, it would be useful to have a put method for the point class that sets both slots of a point object. Such a method could be defined by

```     Self << point(X,Y) :-
Self << x(X),
Self << y(Y).
```

Similarly, a 2-argument get method for the rational number class might be defined as

```     Self >> (N/D) :-
Self >> num(N),
Self >> denom(D).
```

Note that the name of the put message is `(/)/2`, and that the parentheses are needed because of the relative precedences of the `>>` and `/` operators.

Put messages are used to store values in slots. Get messages, however, may be used either to fetch a value from a slot or to test whether a particular value is in a slot. For instance, the following command tests whether the `do_something/2` predicate sets the point object's `x` and `y` slots to 3.14159 and 2.71828, respectively.

```     | ?- create(point, PointObj),
do_something(PointObj),
PointObj >> x(3.14159),
PointObj >> y(2.71828).
```

The `fetch_slot/2` predicate can similarly be used to test the value of a slot.

The effects of a put message (indeed, of any message) are not undone upon backtracking. For example, the following command fails:

```     | ?- create(point, PointObj),
PointObj << x(3.14159),
PointObj << y(2.71828),
fail.
```

But, it leaves behind a point object with `x` and `y` slots containing the values 3.14159 and 2.71828, respectively. In this, storing a value in an object's slot resembles storing a term in the Prolog database with `assert/1`.

Some care is required when storing Prolog terms containing unbound variables in term slots. For example, given the class definition that begins with

```     :- class prolog_term = [public p_term:term].

Self <- create.
```

the following command would succeed:

```     | ?- create(prolog_term, TermObj),
TermObj << p_term(foo(X,Y)),
X = a,
Y = b,
TermObj >> p_term(foo(c,d)).
```

The reason is that the free variables in `foo(X,Y)` are renamed when the term is stored in the `prolog_term` object's `p_term` slot. This is similar to what happens when such a term is asserted to the Prolog database:

```     | ?- retractall(foo(_,_)),
assert(foo(X,Y)),
X = a,
Y = b,
foo(c,d).
```

However, this goal would fail, because `c` and `d` cannot be unified:

```     | ?- create(prolog_term, TermObj),
TermObj << p_term(foo(X,X)),
TermObj >> p_term(foo(c,d)).
```