The documentation in the guide looks relatively straight forward: methods are defined with define/public, for example.
However, when I started to read the documentation in the reference, things started falling apart for me. It's almost as if two different things are documented here. For example, there is no define/public class-clause in class. There is however a public clause.
But when I try to define a method only with public, I get an error:
class: -public element is not an identifier or pair of identifiers
Thus define/public and public is not the same. There is virtually no explanation of what public actually does. Just a code example that I didn't understand. Why exactly does the method call for jump return 'hop?
It seems that the public clause somehow introduces the method jump. But how exactly?
And why is define/public not among the class-clauses?
The define/public form is a macro that expands into both public declaration and a definition. The public form is the "primitive" that tells the class macro which definitions to interpret as methods vs private fields. So when you write
(define counter%
(class object%
(super-new)
(define n 0)
(define/public (click)
(set! n (add1 n))
n)))
the class macro first shallowly expands the class body (using local-expand) to the following (roughly):
Now it fits the grammar from the Reference. The (public click) declaration says to interpret the definition of the identifier click as a method definition. The class macro checks that its right-hand side satisfies the restrictions on methods, rearranges the method code to add the implicit this argument, and arranges for the method to be part of the class (the "vtable") rather than taking up space in each object. Since there isn't any public (or private, etc) declaration for n, its definition is treated as a private field.
The advantage of designing the class form this way is that you can use other Racket macros to define fields and methods, since private field definitions are just ordinary Racket definitions and method definitions are just ordinary Racket definitions plus a declaration. Here's a little toy example about a Point class that uses racket/match definition forms:
(define point%
(class object%
;; Init args:
;; - xy : (list Real Real)
;; Fields:
;; - x, y : Real
;; Methods:
;; - move! : (list Real Real) -> (list Real Real)
(super-new)
(init xy)
(match-define (list x y) xy)
(public move!)
(define/match (move! dxy)
[[(list dx dy)]
(set! x (+ x dx))
(set! y (+ y dy))
(list x y)])))
(define p (new point% (xy (list 1 2))))
(send p move! (list 5 6))
;; => '(6 8)