views:

74

answers:

4

I develop in C++, and sometimes I wish I could say something like this:

class Heading : public float    // this line won't compile
{
public:
  Heading( float const value_ )
  : float(value_)               // this line won't compile
  {
    assert( value_ >= 0.0f );
    assert( value_ <= 360.0f );
  }
};

Instead, I have to do something like:

class Heading : public float
{
public:
  Heading( float const value_ )
  : value(value_)
  {
    assert( value >= 0.0f );
    assert( value <= 360.0f );
  } 
private:
  float value;
};

Are there any programming languages out there that allow you to extend value types?

+3  A: 

Python.

Everything's an object. So extending float is simple.

class Heading( float ):
   def __init__( self, value ):
       assert 0.0 <= value <= 360.0
       super( Heading, self ).__init__( value )

And yes, 0.0 <= value <= 360.0 is legal syntax.

S.Lott
360? You heathen. Should be `2 * math.pi`! :-P
Chris Jester-Young
@Chris: More like between  − *π* and *π* :-)
Joey
Um... The OP was in degrees. And, as a sailor, I use degrees more than radians.
S.Lott
@S.Lott, @Joey: Okay, you both win. :-) (What, so you're into boat-programming?! :-O)
Chris Jester-Young
I'm not familiar with Python, but it seems the assert happens before the base class is initialized, which can only mean one thing: AWESOME. =)
ShaChris23
@Chris Jester-Young. Yes. I need to integrate GPS, Chartplotter and Macintosh.
S.Lott
This is not "inheriting from a value type", though, because Python doesn't *have* value types. Everything is the same, and is equivalent to a reference type in languages in which everything is not the same.
Porculus
@Porculus: I really appreciate that you are trying to be very precise.
ShaChris23
@Porculus: While "This is not "inheriting from a value type" may be true, I'm unclear on what actual, discernible, measurable, visible, pragmatic difference can be seen. Especially considering that Python has no value types. What hair are you splitting? It sure looks like what was requested. In what way does it fail to meet the requirements? Other than "philosophically".
S.Lott
@ShaChris23: strictly speaking, `float` is fully initialized by `__new__`, which is called before `__init__`. this is common of most immutable, interned types in python, because `__init__` is passed a `self` arg. If you needed to modify the instance (say, putting it in the range of `[0,360)`), init would't be able, because the instance is already created and already immutable. You could override `__new__` in a similar fashion as in the answer to get that behavior.
TokenMacGuy
@Porculus: The difference between a value type and a reference type can only be observed in the face of mutability and multiple identities. However, in Python, floats are immutable and their value is their identity. So, it is actually impossible to tell whether floats are value or reference types. For the sake of simplicity, they are described as reference types in the language spec, because that means that there is only one kind of type, which eliminates unnecessary complexity from the spec. But, they behave like (and all existing Python compilers implement them as) value types.
Jörg W Mittag
A: 

D, java, and Objective-C allow deriving from built-in types. In fact most object-oriented languages with built-in types defined to inherit from Object permit inheritance from the built-in types. (I'm sure there's a counterexample and we're about to find out about it in the comments...)

Eric Towers
IMO, the most intriguing answer from your list of languages is D since it's on par with C++ in terms of performance (if not better?) and wins handily in terms of syntax.
ShaChris23
Value types are not the same thing as built-in types. You cannot inherit from `float` in Java -- in fact you can't inherit from the equivalent reference type `Float` either, though that's a library issue rather than a language issue. Objective-C has the same limitation. I don't know about D.
Porculus
C# is a counter-example: all ValueTypes (including built-in int, bool, etc.) inherit from Object but are 'sealed'.
Stephen Swensen
+1  A: 

Ada allows this to a limited extent: specifically, your example can be expressed in Ada as

type Heading is digits 10
    range 0.0..360.0;

Pascal had a similar feature that was, IIRC, restricted to integers.

I don't know of any languages that allow unrestricted inheritance from primitive types like float. Object-oriented inheritance by definition involves inheriting from a class, which something like C++'s float by definition is not.

Porculus
This is *subrange typing*. It's *subtyping*, but not really *inheritance* (at least not in the OO sense of the word). BTW: I really don't understand why so few languages (basically only Pascal and its derivatives) have subrange typing. It's very useful, easy to use, easy to understand and easy to implement.
Jörg W Mittag
+3  A: 

In ruby you can go a step further. You can actually modify built in types.

class Float
  class self.heading(val)
    raise RangeError unless (0.0...360.0) === val
    val
  end
end
TokenMacGuy
Holy crap, that messes up my mind. ;-)
ShaChris23