3 ms·
The basic idea is that objects should know how to represent themselves. In Smalltalk every Object implments writeOn: method, which gets a stream and prints self
by klibertp 13y ago
The basic idea is that objects should know how to represent themselves. In Smalltalk every Object implments writeOn: method, which gets a stream and prints self on this stream.
By extension, if an object knows how to convert itself into another object, it implements a method for doing do. In Smalltalk there is a convention of putting all such methods inside "converting" protocol. For great example of how is this useful you can look at the Collection and it's subclasses in Smalltalk - all collections have many "asOtherKindOfCollection" methds, which are either inherited or implemented, depending on a collection. It's great to be able to send "asSet" to any collection that comes your way and the way Smalltalk does it is natural in purely object oriented languages.
That and the fact that creating IntsToRange or StringToDayOfWeek "static" classes is actually even worse leads to the design where Integers have `to:` and `days` methods.
Actually, there is one more probable cause: in Smalltalk and some other languages extending already defined types is easy, really easy, easier even than creating a new, empty class. The methods are grouped into "protocols", which are grouped into packages and it's - not quite - largely orthogonal to the classes. Combine that with powerful IDE, VC support (Monticello, Metacello) etc. and you have no reason whatsoever not to extend even the most basic classes.
- philwelch 13y agoThe question is what "2.days" actually returns. IIRC, in ActiveSupport it returns an integer number of seconds. Is that a sensible convention? If you had another class representing an span of time (with or without any absolute calendar reference) that an Integer could convert into, that might be a cleaner design. But even in that case you wouldn't necessarily have a method on Integer to confer it to a TimeSpan; you'd initialize a TimeSpan with an integer argument. In general I find it cleaner when less primitive classes can represent themselves as more or equally primitive classes, but not vice-versa. to_integer, to_float, to_list, to_boolean, etc. But on the other extreme, if your application entails establishing database connections, implementing String#to_database_connection would be ridiculous. For me, integers are much more primitive than date and time objects. `2.days` would be equivalent to implementing `2.meters` in a CAD application, but I suppose you might be OK with that. But even granting that an integer can transform itself into a representation of a time span, i.e. `2.days` is okay, `2.days.ago` is right out. That's not just an Integer representing itself as a span of time. Now all of a sudden Integer has to have knowledge and, even worse, opinions about the current date and time (which is one of the most hazardous boundary cases in all of software).
- klibertp 13y ago> integers are much more primitive than date and time objects In terms of concepts, yes, but in terms of language syntax and semantics they are the same (in Smalltalk). > `2.days` is okay, `2.days.ago` is right out Yeah. But not because it "looks bad", and not because Integer would need to know anything more than it does already (it wouldn't), but because `2 days ago` is actually less flexible and harder to maintain. Consider: Date today - 2 days. "27 December 2013" DateAndTime now - 2 days. "2013-12-27T04:43:42.679+01:00" We can get either Date or DateAndTime without changing anything. With proper planning the superclass of both Date and DateAndTime can have a generic - method which will work for all the cases. With the `2.days.ago` we're tied to one result type. We need to code around it, giving it a default argument with a class or remembering the "kind" of Duration. Anyway, if it's ok to have a function which takes integer it's equally ok to have an Integer have a method. Especially when you just can't have a function, like in Smalltalk and the only alternative is writing yet another class with one method in it.
- philwelch 13y ago> Anyway, if it's ok to have a function which takes integer it's equally ok to have an Integer have a method. Seriously? Any function that takes an integer argument? Like, "exit". You want to call 1.exit to terminate a program with a return code of 1? Is there any difference between a function that takes an argument and a method on an object? Shall we implement all functions that take n arguments as multimethods? Are you actually going to implement String#to_database_connection? That was meant as a reductio ad absurdum, I didn't expect anyone to literally follow me there. If you want some particular Integer to get decorated with additional methods because you're using it in some particular domain context but you're not globally changing the interface of all Integers that's a different story. > Especially when you just can't have a function, like in Smalltalk and the only alternative is writing yet another class with one method in it. There are perfectly same object oriented ways to solve this problem, like instantiating some kind of TimeSpan object, or having a singleton for process status in the case of the "exit" function.
- klibertp 13y ago