Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I thought that many object-oriented languages have a reserved keyword for methods which do not modify the state of an object. These methods often have names that start with get. AFAIK a "getter" is always related to a single object attribute and "accessor" is too general, so "readonly" may the right term for this kind of methods (?). To give an example:

object Timespan {
    attribute start
    attribute end

    // getter, not changing the state
    readonly method getStart    { return start } 
    readonly method getEnd      { return end }

    // also not changing the state
    readonly method getDuration { return ( end - start ) }
}

The compiler/interpreter should check that readonly methods have no side-effect by modifying object attributes. I wonder why this language feature is not more common - just naming a method getFoo does not ensure that it won't modify the object.

share|improve this question
2  
This is a feature of functional programming, as far as I know, but not so much of object-oriented programming. There are cases where getters do have to modify object state (e.g. to lazily initialize a value), which is one of the reasons OOP has them in the first place - although I think there is an implicit understanding that a getter shouldn't modify state in a way that "matters," whatever that means. –  David Z Oct 11 '11 at 23:21
    
It means it shouldn't have side effects that will change behavior. If the choice is between initializing something in a ctor vs lazily in a getter - so long as nothing tries to access it without initializing it if needed, there's no effect on behavior. –  kylben Oct 12 '11 at 0:02
    
Declaring methods readonly so the compiler checks they actually are is not very useful. What however is useful is if you can restrict code to only call such methods, so you can pass objects from your internal data by reference and still be sure the other component won't screw up your internal state. Otherwise you either have to define a restricted interface for them (lot of typing and virtual method calls) or clone them (allocation is cheap in managed languages, but not free). –  Jan Hudec Oct 12 '11 at 7:34
    
@David: As far as I understand object-orientation, details of implementations, such as lazy initialization, should be hidden: an object is a piece of data together with methods. I'd count readonly methods to the data part, so you can better separate data and behaviour. However most OO languages seem not support this separation: you must write ugly getters, setters, and const functions mixed with methods that actually do some business logic :-( –  Jakob Oct 12 '11 at 7:36
add comment

4 Answers

In C++ you can declare const member functions. Such methods can't modify object state ( not even potentially, i.e. they can't call non-const methods of the same object), and this is ensured by the compiler.

share|improve this answer
    
Beat me to it by a minute. –  kylben Oct 11 '11 at 21:56
    
Oh yes, now I remember const :-) Sorry for the stupid question, sometimes you just do not find the right term for a concept in your mind. –  Jakob Oct 11 '11 at 22:56
    
(But/and methods can "cast away constness" and modify the state anyway. It's evil, but you can do it. ;-) –  Jeff Grigg Oct 12 '11 at 1:59
    
@Jeff Grigg: If you're determined enough, a program can scan its own memory image to fiddle with bytes directly - no compiler in the world is stopping you from doing things like that. –  tdammers Oct 12 '11 at 5:50
3  
@Sean, yes, but the point of mutable is exactly to let the compiler know that that member is not relevant for the object's state. Typical example is a cached hash value. –  Péter Török Oct 12 '11 at 7:26
show 1 more comment

What you want is const of C++. I generally find it extremely useful and don't understand why other languages don't have it, but they don't. The only other language I know to have something similar is D, but the differences in semantics, while making it more useful to optimization, make it less useful for restricting interfaces.

In other languages like Java and C#, the only thing you can do is create an interface with the constant methods only, implement it in the object and downcast to that interface if you want to pass the object but not allow modifying it. Unlike C++, you won't get compiler checking the methods are in fact constant.

While the interface will serve the ultimate goal of being able to pass the object by reference and still being able the other code will not modify it, using an interface means always incurring the virtual call overhead while in C++ it's purely compile-time affair.

share|improve this answer
    
It seems to be (tell me if you agree) that while some people claim language-enforced const-correctness is "too difficult", the lack of language support doesn't diminish the need for const correctness--it merely makes it harder to achieve. Const correctness in C++ was a problem because C++ libraries had to interact with C libraries that had no such concept, but a new language or framework should be able to largely avoid such handicaps. –  supercat Jan 28 at 21:45
add comment

A method that does not have any observable effect on the state of the object is commonly known as a "pure" method. The key word here is observable. In the case of lazy instantiation or caching - these effects would not necessarily be observable to the consumer, so the method would still be considered a pure method.

In C# (and other languages which support meta data), you can declare an attribute on a method which marks it as pure, and static analysis tools can be used to warn you if it isn't (or more usefully, if it regresses from being pure).

see: http://msdn.microsoft.com/en-us/library/system.diagnostics.contracts.pureattribute.aspx

share|improve this answer
    
Unfortunately such annotations are almost worthless, unless enforced by the compiler. For example one could have a pure method in class A, but a B derived from A still can override that method with an impure one. This should be considered a non tolerable violation of inheritance rules. After all, the whole thing would be useful only if strictly compiler checked. –  Ingo Oct 12 '11 at 13:11
    
@Ingo totally agree, such annotations are not used to their full potential by current compilers (speaking from a .NET perspective as I do). However I do think that annotations are the correct mechanism to express this kind of intent. –  MattDavey Oct 12 '11 at 15:13
    
@MattDavey: Do you have any idea if there's any annotation which would mean the opposite, that could be applied to methods such as System.Drawing.Point.Offset so as to indicate that a compiler should not attempt to replace MyListOfPoint[3].Offset(2,3); with var temp=MyListOfPoint[3]; temp.Offset(2,3); but should instead reject the construct altogether? –  supercat Jan 28 at 21:41
add comment

Python:

@property
def foo():
    return self.__foo

C#:

class Foo
{
    public int bar()
    {
        get
        {
            return 1;
        }
    }
}

It's true that the Python example does not technically make things read-only, but "support" it is. A mechanism to communicate to other programmers that the method is read-only counts as support. And no, it does not simply have to be a trivial getter that only returns an instance field.

share|improve this answer
    
Do you really have to explicitly declare trivial getters, that only return a simple attribute value? –  Jakob Oct 11 '11 at 23:01
2  
Nothing in Python is truly read-only.. This simply does some name mangling that you can get around with the proper know-how. –  Demian Brecht Oct 11 '11 at 23:05
3  
Maybe I misunderstood the question/the answer, but how is a C# getter a "method which do not modify the state of an object" (quote from the question)? It is a bad practice to modify the state of an object in a getter, but technically speaking, nothing forbids you to do it. –  MainMa Oct 12 '11 at 2:57
1  
This does not cut it, because it does not allow methods that have arguments. There are many useful methods that do have arguments, but don't modify the object and there are many cases where you need to pass an object around, but still know that the code you gave it to can't modify it. –  Jan Hudec Oct 12 '11 at 6:50
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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