Several typed
programming languages provide explicit support for the top type. In
statically-typed languages, there are two different, often confused, concepts when discussing the top type. • A
universal base class or other item at the top of a
runtime class hierarchy (often relevant in
object-oriented programming) or
type hierarchy; it is often possible to create objects with this (runtime) type, or it could be found when one examines the type hierarchy programmatically, in languages that support it • A (
compile time)
static type in the code whose variables can be assigned any value (or a subset thereof, like any object pointer value), similar to
dynamic typing The first concept often implies the second, i.e., if a universal base class exists, then a variable that can point to an object of this class can also point to an object of any class. However, several languages have types in the second regard above (e.g., void* in
C, id in
Objective-C, interface {} in
Go), static types which variables can accept any object value, but which do not reflect real runtime types that an object can have in the type system, so are not top types in the first regard. In dynamically-typed languages, the second concept does not exist (any value can be assigned to any variable anyway), so only the first (class hierarchy) is discussed. This article tries to stay with the first concept when discussing top types, but also mention the second concept in languages where it is significant. The following object-oriented languages have no universal base class: • C++ has no universal class like Object. •
Objective-C. It is possible to create a new base class by not specifying a parent class for a class, although this is highly unusual. Object is conventionally used as the base class in the original Objective-C runtimes. In the
OpenStep and
Cocoa Objective-C
libraries, NSObject is conventionally the universal base class. The top type for pointers to objects is id. •
Swift. It is possible to create a new base class by not specifying a parent class for a class. The protocol Any can accept any type.
Other languages Languages that are not object-oriented usually have no universal supertype, or subtype
polymorphism support. While
Haskell purposefully lacks subtyping, it has several other forms of polymorphism including
parametric polymorphism. The most generic type class parameter is an unconstrained parameter a (without a
type class constraint). In
Rust, is the most generic parameter ( is not, as it implies the Sized trait by default). The top type is used as a
generic type, more so in languages without
parametric polymorphism. For example, before introducing generics in
Java 5, collection classes in the Java library (excluding Java arrays) held references of type Object. In this way, any non-intrinsic type could be inserted into a collection. The top type is also often used to hold objects of unknown type. Java supports "
wildcard type parameters", represented by ?. For instance, List denotes a list that can hold any type (but not null pointer|). Wildcards can be bounded, List and List denote a list that can hold any type that inherits from/is an ancestor class of (respectively) type T (including T itself). Wildcards however cannot simultaneously have both upper and lower bounds. The top type may also be seen as the implied type of non-statically typed languages. Languages with runtime typing often provide
downcasting (or
type refinement) to allow discovering a more specific type for an object at runtime. In C and C++, the
void pointer type (void*) can accept any non-function pointer, even though the
void type is not the universal type but the
unit type. In C++, downcasting from void* cannot be done in a
safe way, where failed downcasts are detected by the language runtime. In languages with a
structural type system, the empty structure serves as a top type. For example, objects in
OCaml are structurally typed; the empty object type (the type of objects with no methods), , is the top type of object types. Any OCaml object can be explicitly upcasted to this type, although the result would be of no use.
Go also uses structural typing; and all types implement the empty interface: interface {}, which has no methods, but may still be downcast back to a more specific type. == In logic ==