Another way of looking at this problem is that the object returned by setClass() is an object of class classGeneratorFunction. It's definitely an object. Also, since functions in R are also considered objects, it's an object.
We'll illustrate by adjusting the code from the original post.
personGenerator <- setClass("Person",
slots = c(name = "character",
age = "numeric"))
aPerson <- personGenerator()
At this point, we have a class generator function that generates objects of type Person, and an instance of Person.
We can see this with the str() function.
str(aPerson)
> str(aPerson)
Formal class 'Person' [package ".GlobalEnv"] with 2 slots
..@ name: chr(0)
..@ age : num(0)
Similarly, we can print the structure of the personGenerator() function.
> str(personGenerator)
Formal class 'classGeneratorFunction' [package "methods"] with 3 slots
..@ .Data :function (...)
..@ className: chr "Person"
.. ..- attr(*, "package")= chr ".GlobalEnv"
..@ package : chr ".GlobalEnv"
>
Going back to the Chambers quote, it's recounted in Hadley Wickham's Advanced R as:
To understand computations in R, two slogans are helpful.
-- Everything that exists is an object
-- Everything that happens is a function call
John Chambers quoted in Advanced R, p. 79.
Since the original question was a bit ambiguous, if "S4 class" refers to the thing represented by the return value of setClass(), an object of type classGeneratorFunction, this is indeed an object. However, if the "S4 class" in the original question refers to the content in the arguments of setClass(), the thing representing Person is not an object until code instantiates it as illustrated above with the personGenerator() function.