31

Say we want to provide an abstraction of an "account" in a bank. Here's one approach, using a function object in Python:

def account():
    """Return a dispatch dictionary representing a bank account.

    >>> a = account()
    >>> a['deposit'](100)
    100
    >>> a['withdraw'](90)
    10
    >>> a['withdraw'](90)
    'Insufficient funds'
    >>> a['balance']
    10
    """
    def withdraw(amount):
        if amount > dispatch['balance']:
            return 'Insufficient funds'
        dispatch['balance'] -= amount
        return dispatch['balance']
    def deposit(amount):
        dispatch['balance'] += amount
        return dispatch['balance']
    dispatch = {'balance': 0,
                'withdraw': withdraw,
                'deposit': deposit}
    return dispatch

Here's another approach using type abstraction (i.e., class keyword in Python):

class Account(object):
    """A bank account has a balance and an account holder.

    >>> a = Account('John')
    >>> a.deposit(100)
    100
    >>> a.withdraw(90)
    10
    >>> a.withdraw(90)
    'Insufficient funds'
    >>> a.balance
    10
    """



    def __init__(self, account_holder):
        self.balance = 0
        self.holder = account_holder

    def deposit(self, amount):
        """Add amount to balance."""
        self.balance = self.balance + amount
        return self.balance

    def withdraw(self, amount):
        """Subtract amount from balance if funds are available."""
        if amount > self.balance:
            return 'Insufficient funds'
        self.balance = self.balance - amount
        return self.balance

My teacher started the topic "Object oriented programming" by introducing the class keyword, and showing us these bullet points:

Object-oriented programming

A method for organizing modular programs:

  • Abstraction barriers
  • Message passing
  • Bundling together information and related behavior

Do you think the first approach would suffice to satisfy the above definition? If yes, why do we need the class keyword to do object-oriented programming?

15
  • 2
    Glad you agree. =) Although I don't know Python well enough to give a thorough answer, you might be interested to know that in Javascript the typical way of doing OOP is similar to the "function object" you describe (though we also have prototypal inheritance which allows the objects to "share" methods instead of having separate copies of each method on every object; I assume Python's class does a similar optimization).
    – Ixrec
    May 24, 2015 at 10:11
  • If you want a detailed answer you should ask another question or join the chat room, but the short answer is (if you completely ignore prototypal inheritance, arrays, etc) that's basically true; most JS objects are nothing but dictionaries of string keys to arbitrary values. foo.bar() is usually identical to foo['bar'](), and on rare occasions the latter syntax is actually useful.
    – Ixrec
    May 24, 2015 at 10:19
  • 8
    This is a really important question on your way to a fundamental understanding of OOP. If you're interested, you can read a blog post of mine where I create a simple object system in JavaScript without relying on any of the OOP parts of the language. Your 1st example has an important shortcoming: Where you'd write object['method'](args), Python objects actually do the equivalent of object['method'](object, args). This becomes relevant when a base class calls methods in a child class, e.g. in the Strategy Pattern.
    – amon
    May 24, 2015 at 12:43
  • 13
    As others have noted, this is a perceptive question about OOP. I'll take this opportunity however to note that this is not at all how real banks represent bank accounts. Banks do not have a mutable "account" object that changes when you debit and credit it; they have write-only list of transactions, and then compute the balance from the list of transactions. As a good exercise, try implementing that mechanism in various languages. May 24, 2015 at 15:01

6 Answers 6

66

Congratulations! You rediscovered the well known fact that object orientation can be done without specific programming language support. It is basically the same way objects are introduced in Scheme in this classic text book. Note that Scheme does not have a class keyword or some kind of equivalent, and objects can be created without having even classes.

However, the object orientated paradigm was so successful that lots of languages - and Python is no exception - provide built-in support for it. This is simply to make it easier for developers to use the paradigm and to provide a standard form of object orientation for that language. It is essentially the same reason why lots of languages provide a for loop, though it could be emulated using a while loop with just one or two additional lines of code - simply ease of use.

8
  • "to provide a standard form of object orientation for that language" Do I hear a criticism of JavaScript in there? ;)
    – jpmc26
    May 25, 2015 at 4:10
  • 1
    @jpmc26: not intentionally. And it seems there are some widely accepted standards how objects are created in JavaScript.
    – Doc Brown
    May 25, 2015 at 7:24
  • @overexchange: do you have a question to ask?
    – Doc Brown
    May 26, 2015 at 9:15
  • 1
    @overexchange: Well, what OOP means is debatable, there are different schools of thought, but the SICP definition is pretty much the one from the 3 bullet points in your question. It is definitely about building abstractions, but don't forget points 2 and 3. Yes, the OOP concept encloses "state change", but it allows also the concept of "immutable objects" (like the string class in Java or C#, Python has some mutable and some immutable data types as well). And your first example in your question confirms to that defintion as well as your second example.
    – Doc Brown
    May 26, 2015 at 9:44
  • 2
    @overexchange: this goes back to Alain Kay's definition of object orientation (the inventor of the small talk language). You will find a comprehensive answer in this stackoverflow.com/questions/2347973/… former SO article. IMHO "message passing between objects" in the SICP sense just means not to access the inner data of an object directly, only through a "defined communication protocol". In OO languages like Python this may just mean "call an object's method".
    – Doc Brown
    May 26, 2015 at 11:00
13

I would agree that the first definition satisfies the three points your teacher made. I do not think we need the class keyword for anything. Under the covers, what else is an object but a data structure with with different types of data and functions to work with the data? Of course, the functions are data as well..

I would go even further and say that doing object oriented programming is not so much dependent on the keywords your language provides, you can do object oriented programming in C if you so wished! In fact, the linux kernel employs such techniques.

What you can infer from the class keyword here is, that the language provides support for this kind of construct out of the box, and you do not need to through all the hoops to re-implement the functionality yourself(which is pretty fun task in itself!). Not to mention all the syntactic sugar you might get as well.

9
  • what about inheritance? Are we crucial about subtypes/supertypes in real time? My first approach may not entertain this!! May 24, 2015 at 10:27
  • 5
    Inheritance is in no way required for OOP. You could implement inheritance in your first example as well. It migth not be very "clean" but possible all the same.
    – Zavior
    May 24, 2015 at 10:33
  • 3
    @Zavior that comment makes me think of VB6. Object oriented without inheritance does indeed make for less clean code, to put it mildly.
    – RubberDuck
    May 24, 2015 at 11:24
  • 1
    @overexchange When you think about it, inheritance is all about sharing common code/behaviour between classes. Nothing stops you from repeating all that code all the time. Would be super awful to maintain though. There is a reason why inheritance exists :)
    – Zavior
    May 24, 2015 at 12:21
  • 1
    @Zavior In its most basic form "subclassing" is an abstraction that says "before you return the higher-order dispatch-and-data-having-function I'm defining here (which we'll pretend is a "class" ha ha ha), instantiate the 'superclass' dispatch-and-data-having-function referred to by ThisParentFoo". That's really all it is. When it comes to naive multiple-inheritance that's actually still all it is, but with the caveat that you introduce the "diamond problem", which is why multiple inheritance sucks.
    – zxq9
    May 24, 2015 at 16:16
9

Of course you can!

The Self programming language is a dynamic prototype-based object oriented language in which everything is an object and there is no sense of classes or whatsoever. It's focused in the idea of prototypical objects and the idea of cloning them instead of having classes as templates of how to create objects.

You should check http://www.selflanguage.org/ for more information. I think it is very interesting and if you like OOP it's a good idea to check something that is not that common.

0
0

Not always: it depends on the language. You've demonstrated the ability to do this in Python but (if your question is meant to be language agnostic despite the Python tag) not all languages can do this. Java, for example, mostly can't. Ignoring the class that contains main, there is no way to define arbitrary methods/fields on an object defined within main without the class keyword. Although anonymous classes do exist they require an interface and they can't have any public members except those defined in the interface. While it is possible to define custom interfaces then make anonymous classes for them, this is effectively the same (but less convenient) than simply using a class.

Doc Brown has a great answer but the point I'm trying to make is that I'm sure there's at least one language that won't allow your solution at all.

5
  • As a beginner, to learn "Object oriented programming" concept, yes am trying to be language agnostic. I think "Doc Brown" has given answer on same lines, he told me read sicp text-chap3, which has nothing to do with any language syntax. May 25, 2015 at 0:55
  • I wish I would name a language that absolutely requires using classes in order to validate my answer. But I only know a few languages and alas Java allows a work around. C++ has structs and Javascript flat out allows what you demonstrated. I suspect Smalltalk and Eiffel might require class since I hear they are strictly structured.
    – SkySpiral7
    May 25, 2015 at 1:31
  • As Doc Brown, If I had learn oop using scheme, I wouldn't have asked this question. Unfortunately, version of SICP course that I am learning uses python. May 25, 2015 at 4:53
  • 1
    Every valid Java program must contain the class keyword so that's not much of a surprise. But you absolutely could implement your own object system on top of Java's object system, though I don't know why you want want to do such a thing.
    – Rag
    May 25, 2015 at 9:31
  • 1. Java is really special in this regard, since it has simply thrown away all other keywords that might be used to create custom data structures. Almost all other languages that I know of have either records or closures. 2. Even in java, you can program on a memory built from an array. And you can implement object orientation within that, using the class keyword only because the language requires you to put your functions in classes. Of course, this is extremely theoretic, but even in Java you can do Object Orientation without the builtin classes! May 25, 2015 at 16:33
0

Your teacher's definition completely misses the most important point of object-oriented programming, the one thing that makes it useful and unique. "Message passing" is a bunch of nonsense dreamed up by the Smalltalk folks, and it's been a failure everywhere it's been tried. The true power of OOP is something known as Liskov substitution, and while the concept is fairly simple to describe and understand, the underlying implementation is complex enough that it's essentially impossible to do right without language-level support.

The idea of Liskov substitution is that anywhere where your code is expecting a variable of a certain type, it should be able to accept any type derived from that type and still work correctly without having to have knowledge of the details of the derived type.

For example, GUI frameworks use Liskov substitution all over the place. They tend to have a base Control class that can represent "any control", which defines an interface that knows about basic actions like drawing, resizing, and responding to user input. If you click on a control, the UI framework will call a Click method on the control without having to care about what kind of control it is, and then let the control handle the click in the appropriate way for its own class. A Button control should do something completely different when clicked on than a TextBox control, to give just one example.

So yes, you can create something kind of similar to objects using the nested functions trick described above, but because you can't get inheritance and Liskov substitution that way, it's an extremely limited substitute for true OOP.

8
  • In C language, can't I say 'struct parent{}' and then 'struct child{ struct parent *ptr;}'? Is this not inheritance in non-oop language syntax? Jun 26, 2015 at 14:58
  • @overexchange: That's a non-OO attempt to fake it, but the compiler won't let you substitute one for the other. (You can't pass a child* to a function that takes a parent* as an argument, at least not without a typecast.) And even worse, C structs can't have methods bound to them, and there's no support for virtual methods, which are what make the magic of Liskov substitution work, so you have to construct VMTs by hand, which is a complicated process that's easy to screw up. Jun 26, 2015 at 15:04
  • 1
    The Linux kernel uses an emulation of several OO techniques, which all have to be coded manually without language support. This leads to plenty of opportunities for bugs, which, being Linux, is counterbalanced by a liberal application of Linus's Law. Yes, it's possible to do--Turing equivalence proves this--but my point that it's extremely difficult to get right without language support still stands. Also, why all these questions about C when the question was about Python? In C it's not possible to do the nested functions trick in the first place. Jun 26, 2015 at 15:32
  • 1
    @overexchange Since when is Java a "programmers paradise"?
    – Brandin
    Sep 15, 2015 at 9:28
  • 1
    Message passing has not been a failure in Smalltalk, Erlang, or even Java-style OOP systems where "message" means something different than "function call" (Qt's signals & slots with a threadsafe queue VS old Java marketing using the term "message" when it means "method call"). Messages != function calls. Genuine messaging is not only successful, it appears to be the only way we know to write massively concurrent and robust systems. This is orthogonal to implementing Java-style OOP without the 'class' keyword. It can be done. It is not always useful. Messaging is beside the point.
    – zxq9
    Oct 23, 2015 at 6:27
-1

Quick Short Answer

Yes, Programmers can apply the Object Oriented Programming without "Classes".

Long Boring Extensive Descriptive Answer

There are several variations of "Object Orientation", altought, the first concept that comes to the mind of many programmers is "Classes".

Yes, Programmers can apply the Object Oriented Programming without "Classes", but, is limited to the features and limitations from each programming language.

Your post is tagged as Python, therefore, your question title may be more like "How to implement Object Oriented Programming without Classes in Python".

I currently use the "Object and Class Oriented Programming" phrase, to identify from other variations like Javascript's "Prototyping", or Visual Basic "Based", or emulation in "Pure C" using "functors".

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