3

I was wondering about why some languages choose to implement numeric types (boolean, integers, floats, characters etc.) as classes/objects (eg. Kotlin) and some as primitive types (eg. Java). I am specifically considering interpreted languages rather than compiled languages.

Below are the differences that I was able to come up with:

As a class:

  • The type could then be extended, so that new classes could be treated as numeric types as well (i.e. being applicable to arithmetic operators).

  • No need for wrapper classes, as the type's relevant functionality could be encapsulated within the numeric type's class itself.

As a primitive:

  • Less memory usage, as only the primive's value would be stored, rather than the extra bulk needed for an object.

What could any other reasons be?

Edit: This is not a duplicate of this question, as this question is purely about language-design, rather than what should be chosen for a specific practical and real-world problem.

6
  • 2
    Primitives have better performance characteristics. They typically have pass-by-value semantics, which makes more sense since they're actually values. "Everything is an object" is a simpler language design. Commented Apr 22, 2015 at 21:00
  • 1
    Consider how you do "foo = bar + 3" in each language type. Take Smalltalk as an example. Compare the amount of work to how it would be as primitives.
    – user40980
    Commented Apr 22, 2015 at 21:04
  • I can't think of a scenario where extending a numeric class would be desirable, and wrapper classes have more to do with working around questionable language decisions (e.g. Java's generics only work with reference types) than encapsulating functionality.
    – Doval
    Commented Apr 22, 2015 at 21:20
  • 1
    It's basically a dirty hack when your language design doesn't allow arbitrary types to have the benefits of unboxed/value types but you want the micro benchmark performance for the most common types. (That is not to say that "hack" can't be better than extending the language or giving up on that performance boost, but I do have a distaste for it.)
    – user7043
    Commented Apr 22, 2015 at 21:26
  • 2
    One should remember Java's origins and the early concerns of performance (along with its adherence to backwards compatibility). Languages designed since have had the benefit of years of R&D and retrospective analysis on what different languages got right and wrong. -- Also, compiled vs interpreted is a red herring (that's an implementation detail) - languages are languages.
    – user40980
    Commented Apr 22, 2015 at 22:05

1 Answer 1

7

One of the most important characteristics that make a programming language efficient is the closeness of the supported data types to the native data types of the underlying hardware. An int primitive directly corresponds to a machine word; it does not get any better than that. The moment you turn the int primitive into an Integer object you have degraded performance of integer operations by an order of magnitude.

Now, modern applications are mostly GUIs which don't do much other than sitting waiting for user input, so in many cases efficiency does not really matter, and ease of use considerations take precedence.

It is very useful and it keeps many things simple to be able to treat numeric types as objects because then you can apply uniform operations on them without having to write special code for each one of them separately.

For example, by implementing the Comparable interface, Integer objects know how to compare themselves against other Integer objects, and Double objects know how to compare themselves against other Double objects, so essentially the quicksort routine and the binary search routine only need to be implemented once, to simply work with any kind of comparable object.

That having been said, let me repeat that if you write an application that has any number-crunching whatsoever to do, primitives are definitely the way to go.

Also it might be worth noting that one of the most beautiful things about C# is that it has managed to achieve the best of both worlds in this respect: it has structs, which are value types that map (perhaps not perfectly, but fairly well) to native machine types, and at the same time are capable of implementing interfaces the way objects do.

5
  • Actually, it was a crappy answer, because only 10% of it addressed your actual question. I amended it, and now it is hopefully better.
    – Mike Nakis
    Commented Apr 22, 2015 at 21:30
  • The Comparable thing is arguably not a very good motivation to have numeric classes. If you want any other ordering (e.g. sorted in reverse) Comparable won't help you.
    – Doval
    Commented Apr 22, 2015 at 21:39
  • 1
    @Doval yes it will. In this case you will make use of a comparator, the default implementation of which simply delegates to the comparables, and then you can trivially write an inversing comparator which negates the integer result of the comparison before returning it. You still get to use the single sorting/searching method of the standard library, and you still get to work with any kind of comparables that might be thrown at you, you only have to write a few extra lines of code to achieve reverse sorting.
    – Mike Nakis
    Commented Apr 22, 2015 at 21:46
  • @Doval actually, you don't even have to write those extra lines of code, someone has already written them, see java.util.Collections.reverseOrder().
    – Mike Nakis
    Commented Apr 22, 2015 at 21:54
  • @MikeNakis Once you've offloaded the work to a "comparator" there's no longer any need for the integers to be objects (other than completely artificial reasons like Java's generics simply not working on non-reference types. That wouldn't be an issue in other languages.)
    – Doval
    Commented Apr 22, 2015 at 21:57

Not the answer you're looking for? Browse other questions tagged or ask your own question.