The type \(\rm SELF\_TYPE\) is used to refer to the type of the \(\rm self\) variable. This is useful in classes that will be inherited by other classes, because it allows the programmer to avoid specifying a fixed final type at the time the class is written. For example, the program
class Silly { copy() : SELF_TYPE { self }; }; class Sally inherits Silly { }; class Main { x : Sally <- (new Sally).copy(); main() : Sally { x }; };
Because \(\rm SELF\_TYPE\) is used in the definition of the \(\rm copy\) method, we know that the result of \(\rm copy\) is the same as the type of the \(\rm self\) parameter. Thus, it follows that \(\rm (new Sally).copy()\) has type \(\rm Sally\), which conforms to the declaration of attribute \(\rm x\).
Note that the meaning of \(\rm SELF\_TYPE\) is not fixed, but depends on the class in which it is used. In general, \(\rm SELF\_TYPE\) may refer to the class \(\rm C\) in which it appears, or any class that conforms to \(\rm C\). When it is useful to make explicit what \(\tt SELF\_TYPE\) may refer to, we use the name of the class \(\rm C\) in which \(\rm SELF\_TYPE\) appears as an index \(\tt SELF\_TYPE_{C}\). This subscript notation is not part of Cool syntax--it is used merely to make clear in what class a particular occurrence of \(\rm SELF\_TYPE\) appears.
From Definition 4.1, it follows that \(\tt SELF\_TYPE_{X} \leq SELF\_TYPE_{X}\). There is also a special conformance rule for \(\rm SELF\_TYPE\):
\[ \tt SELF\_TYPE_{C} \leq P\ \ if\ \ C \leq P \]Finally, \(\rm SELF\_TYPE\) may be used in the following places: \(\rm new\ SELF\_TYPE\), as the return type of a method, as the declared type of a \(\rm let\) variable, or as the declared type of an attribute. No other uses of \(\rm SELF\_TYPE\) are permitted.