문제

I do not have any argument opposing why we need only a single universal class. However why not we have two universal classes, say an Object and an AntiObject Class. In nature and in science we find the concept of duality - like Energy & Dark Energy; Male & Female; Plus & Minus; Multiply & Divide; Electrons & Protons; Integration & Derivation; and in set theory. There are so many examples of dualism that it is a philosophy in itself. In programming itself we see Anti-Patterns which helps us to perform work in contrast to how we use Design patterns. I am not sure, but the usefulness of this duality concept may lie in creating garbage collectors that create AntiObjects that combine with free or loose Objects to destruct themselves, thereby releasing memory. Or may be AntiObjects work along with Objects to create a self-modifying programming language - that allows us to create a safe self modifying code, do evolutionary computing using genetic programming, do hiding of code to prevent reverse engineering.

We call it object-oriented programming. Is that a limiting factor or is there something fundamental I am missing in understanding the formation of programming languages?

도움이 되었습니까?

해결책

This is only an answer to answer the question in the title.

Languages such as Java have every class deriving from Object for two reasons.

Firstly, to increase the amount of polymorphism available. This was particularly required before generics were added to the language. Without Object, collection classes would be impossible to write in a useful fashion.

Secondly, there are many methods that classes are expected to have or are useful, and these are collected in Object. By ensuring that all classes inherit from Object, all classes will implement the same minimal interface.

As mentioned in a comment, C++ does not have a class like Object. C++ is in many ways untyped, so the issues I mention above are not applicable. Also, C++ templates provide a lot of polymorphism and are used to implement collections.

다른 팁

I think the accepted answer covers pretty much the original question, but I would like to supplement it (if I may) slightly by throwing in (quite informally) a few ideas regarding the secondary questions.

From an inheritance point of view, nothing prevents the class hierarchy to have several roots. As it has been pointed out by other peoples, C++, as well as many OO languages don't constraint expressiveness to a single root ancestor class.

However, from a type theoretic point of view (recall that inheritance and subtyping are not the same thing, so I am probably stepping out of the frame of the main question here), a single "top" supertype can make a lot of sense (depending on the type theory of course). For instance, in OCaml, there is a common supertype to all objects (whether class instances, or immediate objects), written < > to denote that the object type is empty, i.e. doesn't accept any message. This seems indeed the most general object type we can define, since we cannot remove anything from it to make it more general. Hence, in this conception of object types, there is necessarily a supertype to all object.

Regarding the dual of the root object, scala sports a class called Nothing, which curiously is also empty, and is the subtype of every other classes. It cannot be instantiated, but holds enough useful semantic to implement the empty list, which is called Nil, and is equal to List[Nothing] (as pointed out in comments, it is possible that programmer never directly use that value in most case, making it seemingly not as useful as it is). Nothing could be considered a dual of the root type - called Any in scala, however these types not only cover classes, but also primitives types, so that everything can be upcasted to Any, for instance.

The ability to define collections that can hold arbitrary kinds of things, without needing to define different methods for different kinds of things, is very useful. Templates in C++ make it possible for a single source file to define collection types that can hold many different kinds of things, but the compiler will have to duplicate the code for every different kind of thing in the collection. If instead one defines almost all of the types in the system to derive from a single type, then a collection which can hold references to things of that type will be able to hold references to things of almost any type.

This approach does have a limitation, however, which is that it blurs the distinctions between values and entities. A reference which encapsulates a value by identifying some particular object can be replaced with a reference to a copy of that object without altering its semantics. A reference which is used to identify an entity, however, cannot be replaced in such fashion. Either the entity itself will be something that can't be copied (e.g. if it represents a connection to something in the real world) or the entity may encapsulate the set of references that exist to it. A key thing to note is that objects behave as values when either they cannot change or only one reference exists to them, and they behave like entities when multiple references exist.

Blurring the distinction between values and entities makes it difficult for collection types to know whether they should regard their contents as values or entities; this in turn limits the ability of collections to implement things like equals or clone in useful fashion. Languages which make a stronger type/entity distinction can have collections do more things automatically than languages which do not, but the distinctions add some complexity, which language designers may or may not feel is justified by the benefits.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 cs.stackexchange
scroll top