14

I know this seems like a weird question, since the point of two or more objects sharing the same class is that their behavior is the same, i.e. their methods are identical.

However, I'm curious if there are any OOP languages that allow you to redefine the methods of objects in the same way that you can assign different values for their fields. The result would be objects constructed from the same class no longer exhibiting the exact same behavior.

If I'm not mistaken, you can do this JavaScript? Along with this question, I ask, why would someone want to do this?

5
  • 9
    The technical term is "prototype-based". Searching for it will give you much material about this flavor of OOP. (Be aware that a lot of people do not consider such structures proper "classes", precisely because they don't have uniform attributes and methods.) Nov 10, 2014 at 15:26
  • 1
    you mean like how two different instances of a button could do different things when they're clicked, because they're each wired up to a different button handler? Of course, one could always argue they do the same thing - they call their button handler. Anyway if your language supports delegates or function pointers then this is easy - you have some property/field/member variable that holds the delegate or function pointer, and the implementation of the method calls that and away you go. Nov 10, 2014 at 15:27
  • 2
    It's complicated :) In languages where slinging function references around is common, it's easy to pass some code into a setClickHandler() method and make different instances of the same class do very different things. In languages that don't have convenient lambda expressions, it's easier to create a new anonymous subclass just for a new handler. Traditionally, overriding methods was considered the hallmark of a new class, while setting the values of attributes wasn't, but especially with handler functions, the two have very similar effects, so the distinction becomes a war about words. Nov 10, 2014 at 15:45
  • 1
    Not exactly what you're asking, but this sounds like the Strategy design pattern. Here you have an instance of a class that effectively changes it's type at runtime. It's a bit off topic because it's not the language that allows this but worth mentioning because you said "why would someone want to do this"
    – tony
    Nov 11, 2014 at 7:36
  • @Killian Forth Prototype-based OOP does not have classes by definition and thus, does not quite match what the OP is asking about. The key difference is a class is not an instance.
    – eques
    Nov 11, 2014 at 14:28

10 Answers 10

9

Methods in most (class-based) OOP languages are fixed by type.

JavaScript is prototype-based, not class based and so you can override methods on a per-instances base because there is no hard distinction between "class" and object; in reality, a "class" in JavaScript is an object which is like a template for how the instances should work.

Any language which allows first-class functions, Scala, Java 8, C# (via delegates) etc, can act like you have per-instance method overrides; you would have to define a field with a function type and then override it in each instance.

Scala has another posibility; In Scala, you can create object singletons (using the object keyword instead of the class keyword), so you can extend your class and override the methods, resulting in a new instance of that base class with overrides.

Why would someone do this? There could be dozens of reasons. It might be that the behavior needs to me more tightly defined than using various field combinations would allow. It could also keep the code decoupled and organized better. In general however, I think these cases a rarer and there often is a more straightforward solution using field values.

5
  • Your first sentence doesn't make sense. What does class-based OOP have to do with fixed types?
    – Bergi
    Nov 10, 2014 at 18:25
  • I mean that per type the set and definitions of methods are fixed or in other words, to add or change a method, you must create a new type (e.g. by subtyping).
    – eques
    Nov 10, 2014 at 18:31
  • @Bergi: In class based OOP the word "class" and "type" essentially mean the same thing. Since it doesn't make sense to allow type integer to have the value "hello" it also doesn't make sense to have type Employee to have values or methods that don't belong to class Employee.
    – slebetman
    Nov 11, 2014 at 2:41
  • @slebetman: I meant that a class-based OOP language does not necessarily have strong, statically enforced typing.
    – Bergi
    Nov 11, 2014 at 3:11
  • @Bergi: That's the meaning of "most" in the answer above (most means not all). I'm merely commenting on your "what does it have to do" comment.
    – slebetman
    Nov 11, 2014 at 3:17
6

It's hard to guess the motivation for your question, and so some possible answers might or might not address your real interest.

Even in some non-prototype languages it is possible to approximate this effect.

In Java, for example, an anonymous inner class is pretty close to what you're describing - you can create and instantiate a subclass of the original, overriding just the method or methods you want to. The resulting class will be an instanceof the original class, but will not be the same class.

As to why you'd want to do this? With Java 8 lambda expressions, I think that many of the best use cases go away. With earlier versions of Java, at least, this can avoid a proliferation of trivial, narrow-use classes. That is, when you have a large number of related use-cases, differing in only a tiny functional way, you can create them almost on-the-fly (almost), with the behavioral difference injected at the time you need it.

That said, even pre-J8, this can often be refactored to shift the difference into a field or three, and inject them in the constructor. With J8, of course, the the method itself can be injected into the class, though there may be a temptation to do so when another refactoring may be cleaner (if not as cool).

6

You asked for any language that provide per-instance methods. There is already an answer for Javascript, so let's see how it is done in Common Lisp, where you can use EQL-specializers:

;; define a class
(defclass some-class () ())

;; declare a generic method
(defgeneric some-method (x))

;; specialize the method for SOME-CLASS
(defmethod some-method ((x some-class)) 'default-result)

;; create an instance named *MY-OBJECT* of SOME-CLASS
(defparameter *my-object* (make-instance 'some-class))

;; specialize SOME-METHOD for that specific instance
(defmethod some-method ((x (eql *my-object*))) 'specific-result)

;; Call the method on that instance
(some-method *my-object*)
=> SPECIFIC-RESULT

;; Call the method on a new instance
(some-method (make-instance 'some-class))
=> DEFAULT-RESULT

Why?

EQL-specializers is useful when the argument subject to dispatching is supposed to has a type for which eql makes sense: a number, a symbol, etc. Generally speaking, you don't need it, and you simply have to define as many subclasses as needed by your problem. But sometimes, you only need to dispatch according to a parameter which is, for example, a symbol: a case expression would be limited to the known cases in the dispatching function, whereas methods can be added and removed any time.

Also, specialization on instances is useful for debugging purposes, when you want to temporarily inspect what happens with a specific object in your running application.

5

You can also do this in Ruby using singleton objects:

class A
  def do_something
    puts "Hello!"
  end
end

obj = A.new
obj.do_something

def obj.do_something
  puts "Hello world!"
end

obj.do_something

Produces:

Hello!
Hello world!

As for uses, this is actually how Ruby does class and module methods. For example:

def SomeClass
  def self.hello
    puts "Hello!"
  end
end

Is actually defining a singleton method hello on the Class object SomeClass.

2
  • Do you want to extend your answer with modules and extend-method? (Just to show some other ways to extend objects with new methods)?
    – knut
    Nov 10, 2014 at 17:17
  • @knut: I'm pretty sure that extend actually just creates the singleton class for the object and then imports the module into the singleton class.
    – Linuxios
    Nov 10, 2014 at 17:19
5

You can think of per-instance methods as allowing you to assemble your own class at runtime. This can eliminate a lot of glue code, that code which has no other purpose than to put two classes together to talk to each other. Mixins are a somewhat more structured solution to the same sorts of problems.

You're suffering a little from the blub paradox, essentially that it's difficult to see the value of a language feature until you've used that feature in a real program. So look for opportunities where you think it might work, try it out, and see what happens.

Look in your code for groups of classes that differ only by one method. Look for classes whose sole purpose is combining two other classes in different combinations. Look for methods that do nothing else but pass a call through to another object. Look for classes that are instantiated using complex creational patterns. Those are all potential candidates to be replaced by per-instance methods.

1

Other answers have shown how this is a common feature of dynamic object-oriented languages, and how it can be emulated trivially in a static language that has first-class function objects (e.g. delegates in c#, objects that override operator () in c++). In static languages that lack such a function it is harder, but can still be achieved by using a combination of the Strategy pattern and a method that simply delegates its implementation to the strategy. This is in effect the same thing you'd be doing in c# with delegates, but the syntax is a bit messier.

0

You can do something like this in C# and most other similar languages.

public class MyClass{
    public Func<A,B> MyABFunc {get;set;}
    public Action<B> MyBAction {get;set;}
    public MyClass(){
        //todo assign MyAFunc and MyBAction
    }
}
1
  • 1
    Programmers is about conceptual questions and answers are expected to explain things. Throwing code dumps instead of explanation is like copying code from IDE to whiteboard: it may look familiar and even sometimes be understandable, but it feels weird... just weird. Whiteboard doesn't have compiler
    – gnat
    Nov 10, 2014 at 19:51
0

Conceptually, even though in a language like Java all instances of a class must have the same methods, it is possible to make it appear as though they don't by adding an extra layer of indirection, possibly in combination with nested classes.

For example, if a class Foo may define a static abstract nested class QuackerBase which contains a method quack(Foo), as well as several other static nested classes deriving from QuackerBase, each with its own definition of quack(Foo), then if the outer class has a field quacker of type QuackerBase, then it may set that field to identify a (possibly singleton) instance of any one of its nested classes. After it has done so, invoking quacker.quack(this) will execute the quack method of the class whose instance has been assigned to that field.

Because this is a fairly common pattern, Java includes mechanisms to automatically declare the appropriate types. Such mechanisms are not really doing anything that couldn't be done by simply using virtual methods and optionally-nested static classes, but they greatly reduce the amount of boilerplate necessary to produce a class whose sole purpose is to run a single method on behalf of another class.

0

I believe that is the definition of a "Dynamic" language like ruby, groovy & Javascript (and Many Many others). Dynamic refers (at least in part) to the ability to dynamically redifine how a class instance might behave on the fly.

It's not a great OO practice in general, but for many dynamic language programmers OO principles aren't their top priority.

It does simplify some tricky operations like Monkey-Patching where you might tweak a class instance to allow you to interact with a closed library in a way they didn't forsee.

0

I'm not saying it's a good thing to do, but this is trivially possible in Python. I can't thing of a good use case off the top of my head, but I'm sure they exist.

    class Foo(object):
        def __init__(self, thing):
            if thing == "Foo":
                def print_something():
                    print "Foo"
            else:
                def print_something():
                    print "Bar"
            self.print_something = print_something

    Foo(thing="Foo").print_something()
    Foo(thing="Bar").print_something()

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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