First, length not a typical generic function, but rather an " Internal Generic Function ". You can see this by looking at its definition:
> length function (x) .Primitive("length")
Compare this to a typical common function:
> print function (x, ...) UseMethod("print") <bytecode: 0x116ca6f90> <environment: namespace:base>
length calls directly to .Primitive , which then can send if it does not handle the call itself; a typical approach calls UseMethod directly, which handles only sending. Also note that there is no length.default function, because the code in the .Primitive call does this:
> methods("length") [1] length.function length.pdf_doc* length.POSIXlt
I'm not sure if it is fully defined when Internal Generic will look at user-defined methods and when it will use only internal ones; I think the general idea is that for a certain class of (efficient, non-core) user / package, the provided methods will be used. But overriding for inner classes may or may not work.
In addition, although this is not of particular importance for this case, even for a typical general method, the documentation is ambiguous as to what should happen when the class is implicitly displayed and not set as an attribute. First, which class() reports are a union of things. On the class help page:
Many R objects have a class attribute, a character vector that gives the names of the classes from which the object inherits. If an object does not have a class attribute, it has an implicit class, "matrix" , "array" or the result of mode(x) (except that integer vectors have an implicit class "integer" ).
Therefore, although class returns the same for f and g , they do not match.
> attributes(f) $srcref function() 1 > attributes(g) $srcref function() 2 $class [1] "function"
Now, this is where it gets mixed. Method distribution is discussed in (at least) 2 places: the class help page and the UseMethod help UseMethod . UseMethod says:
When the function that calls UseMethod("fun") is applied to an object with the class c("first", "second") attribute c("first", "second") , the system searches for a function named fun.first and, if it finds it, applies it to the object. If no such function is found, a function called fun.second is checked. If the class name does not create a suitable function, the fun.default function is used if it exists or an error occurs.
While the class says:
When the general fun function is applied to an object with the class c("first", "second") attribute c("first", "second") , the system searches for a function named fun.first and, if it finds it, applies it to the object. If such a function is not found, a function called fun.second . If the class name does not create a suitable function, the fun.default function is fun.default (if one exists). If the class attribute is missing, the implicit class is used, and then the default method.
The real difference in the last sentence is that there is no UseMethod on the class page. UseMethod does not say what happens if there is no class attribute; class says an implicit class is used for submission. Your code seems to indicate that what is described in the class is incorrect, as length.function was called for g .)
What really happens when the method is submitted when there is no class attribute, you may need to examine the source code, as the documentation does not seem to help.