I know that obviously every language has its own characteristics and implementations, but from a theoretical standing point, viewing OOP as an abstract programming paradigm, does it allows side effects? Does it change the program state?

Every object has its own state and an object can change its own state or another object's state. So, is this state the same with the program state? And thus, OOP is not stateless?

On the other hand, OOP allows for side effects (observable interactions between objects, modify global vars).

So OOP is stateful and allows side effects? Did I got it right?


There is no universal definition of OOP. It is therefore difficult to make a statement like “OOP is stateful”. There are both examples where OOP involves state and examples where OOP is used without any state. OOP tends to be paired with imperative programming, which certainly allows side effects and mutable state.

There is one line of thought that OOP is about encapsulation. OOP is not needed to organize the program state into smaller records/structs. But if we turn those records into objects and encapsulate this data behind a message-passing interface, we can disentangle the program state, leading to a more decoupled and modularized architecture.

That way the state is still there, but we can look at parts of the state (each object) in isolation. There won't be any outside interference. If outside users want to access or change the state, they will have to call a method that we control. It is now easier to reason about an object. Conversely, outside users only need to know about the public interface and not all internal details, which makes their life easier as well.

So one could say that OOP is a technique for managing program state more easily.

Using OOP for encapsulation like this lends itself well to larger software systems, at least in theory. This idea is not restricted to single object instances in a programming language. One could also view larger architectures as object-oriented, e.g. in a microservice architecture each individual microservice can be interpreted as an object.

In most OOP-ish programs this state management is not done cleanly. Any time you access a global variable or call a static function you are side-stepping the decoupling benefits of only communicating via method calls. This will come back to bite you if you write unit tests for an object – any data flow through static members is data flow you can't intercept, mock, and verify.

OOP is not the only way to manage state within a larger application. Most of these features like “encapsulation” are merely an example of the modular programming paradigm, but there's no clear line between modular and object-oriented programming. Instead of parcelling state into smaller chunks that send messages to each other, functional programming suggests making all state explicit and immutable. The program flow can then be interpreted as state transformations rather than state mutations.

  • Thanks for the detailed answer. One thing. Can you elaborate a little more on the "state transformations rather than state mutations" ? What is the difference between state transformation and state mutation? Do you have any links? Thanks
    – slevin
    Aug 10 '17 at 18:58
  • 3
    @slevin With state mutation I mean that the state is changed: process(state). Sometimes this state is hidden/implicit/global. With state transformation, a new state is created and the old state left unchanged: newState = process(oldState). By making all state explicit, the process is completely characterized by its input and output, i.e. behaves like a pure mathematical function. There is no hidden state. This is easier to analyze, understand, and test. Functional programming prefers this explicitness, but it isn't perfect either: this focus on mathematical purity often gets in the way.
    – amon
    Aug 10 '17 at 19:52
  • 1
    Good answer. No universal definition of OOP, it is true, but going back to the first object oriented language (smalltalk), does serve to remind us of the original motivations behind the ideas. Lately I often hear about the "right" and "wrong" way to do OOP, to the detriment of the industry. Aug 10 '17 at 22:27
  • @FrankHileman: As far as I know, SIMULA 67 is older than Smalltalk. Also, I attended a course on programming languages which maintained that dynamic dispatch is what characterizes OO. Other features like encapsulation, state mutation and so on, are only found in particular flavours of object orientation.
    – Giorgio
    Aug 11 '17 at 9:52
  • 1
    Keep in mind that not all static members are bad. There are several use cases (Math functions being the most common example) that lend themselves very well to be implemented as static. You can unit test static stuff, despite what most people say about them - albeit you need to take some care to implement only pure functions (as in, no side effects) as your static stuff.
    – T. Sar
    Aug 11 '17 at 11:20

Here's a somewhat heterodox but, I (biasedly) think, interesting perspective.

Originally, my opinion was that state and object identity were not integral parts of OO "in theory", though they are ubiquitous in practice. It's quite easy (if unusual) to avoid mutable state entirely in an OO language like Java (modulo wanting to use standard libraries...) For example, Abadi and Cardelli had both mutable and immutable versions of their ς-calculus which was intended to be for OO what the λ-calculus is for FP. Suffice it to say, neither it nor any other "object calculus" has actually managed to claim such a role.

There's basically only one other "calculus" that has gained significance even approaching the λ-calculus' and that's Milner's π-calculus which was designed for reasoning about concurrent systems. My views changed after writing a decent amount of code in a π-calculus style, and particularly when discovering the blue and deep blue calculi which note that code written in the π-calculus tends to look and feel like working in continuation-passing style and endeavors to provide a "direct style" variation of the π-calculus. The result is rather like a concurrent OO language (and one that can smoothly capture the ς-calculus no less). Similarly, even writing code in the π-calculus tends to produce patterns that are very reminiscent of OO-style objects.

This perspective provides a firm footing for many, but not all, aspects of OO languages, and concurrency and OO have been interrelated in a variety of ways (actor model, active objects, the discrete event simulations of Simula, message passing) throughout the history of OO. Of course, most modern OO languages don't emphasize concurrency. Indeed, the vision of OO this perspective suggests looks a lot more like Erlang than Java. Nevertheless, this perspective does entail that mutable state and object identity are inherent. While within a "process" we may not have mutable state, as in Erlang where each process' body is (mostly) purely functional, it's trivial to model mutable state as a process. Similarly, while the π-calculus doesn't have anything like reference equality and it's non-trivial to model it, it's nevertheless clear that two processes are distinct even if they have the exact same definition. (In Erlang/actor terms, they have different "mailboxes".)


I believe that Object-Oriented does allow side effects and state changes but well-designed object systems do it in one relatively small, well-delimited bubble at a time. Actor-based platforms are a good example of this principle followed strictly.

If you look at Alan Kay's account of the beginnings of Smalltalk (the language that introduced the term object-oriented) and early OO languages, whether to ultimately change state or not didn't even seem to be a question back then. It was implied that something had to be mutable in order for a system to run, but what really mattered was how and whether the calling object should be aware of any of it. Namely, the big idea was that objects had an internal memory, one that couldn't be modified from the outside with direct fine grained assignments, but could only be transitioned by calling methods reflecting higher-level behaviors of the object.

  1. Everything is an object
  2. Objects communicate by sending and receiving messages (in terms of objects)
  3. Objects have their own memory (in terms of objects)


The last thing you wanted any programmer to do is mess with internal state even if presented figuratively. Instead, the objects should be presented as sites of higher level behaviors more appropriate for use as dynamic components.


It is unfortunate that much of what is called "object-oriented programming" today is simply old style programming with fancier constructs. Many programs are loaded with "assignment*style" operations now done by more expensive attached procedures.


However, doing encapsulation right is a commitment not just to abstraction of state, but to eliminate state oriented metaphors from programming.

(In The Early History of Smalltalk, p. 19, 25)

  • Very good research! My own interpretation of those comments was that the state machine, and system invariants, are all encapsulated. However, nowhere is it implied in your quotes that objects must have mutable state. I have always assumed that traditional functional style programming, including pure functions, would often exist at the end of call chains. For example, a square root function needs no mutable state, and it may call other pure functions within. The type of "old style programming" he refers to has to do with the over use of mutable state -- still a problem today. Aug 11 '17 at 23:14
  • Thank you. I believe he refers to something more specific though - mutable state by use of direct assignment statements. This is your setters in nowadays' OO. In contrast, nowhere does he mention that mutating state indirectly through high-level method calls is problematic. Actually, the words mutable or mutability never appear in the paper. Aug 12 '17 at 0:36
  • you are right: "The last thing you wanted any programmer to do is mess with internal state even if presented figuratively. Instead, the objects should be presented as sites of higher level behaviors more appropriate for use as dynamic components." It is all about encapsulation and semantics in method names; using objects without knowing about internal details to achieve higher levels of abstraction. Aug 13 '17 at 23:05

Most OOP languages allow you to create static classes, which are basically stateless objects. If that were all it would be pretty sad, fortunately you can also make classes that serve as templates for creating instances, in other words stateful objects. For any less than utterly trivial application you will need the latter kind.

State is not bad, without it IT would be limited to some very simple control functions.

  • 2
    There are entire programming languages that are almost entirely without mutable state. Aug 10 '17 at 13:02
  • @NickKeighley They don't allow you to modify an objet, but you just assign the reference of the new one in place of the old one. The new one being a modified version of the old one. If you think like a C dev, consider that you're using pointer and they allow you only to modify where the pointer point and not the content. In the end both can achieve the same result.
    – Walfrat
    Aug 10 '17 at 14:06
  • Your first sentence is incorrect: static classes may have state, and often do. e.g. a Math class might have a static property PI, which is a state. However, the state is usually immutable. In Java at least, a static class can have modifiable state, though that is usually a bad idea.
    – user949300
    Aug 10 '17 at 14:32
  • @user949300 you are conflating static objects with static classes. You are right about static classes often having members
    – Caleth
    Aug 10 '17 at 14:36
  • 1
    I think what you mean are immutable classes, not static classes.
    – Philipp
    Aug 11 '17 at 9:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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