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
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
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).
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.
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
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.
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.
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
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.
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.
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()