I had quite a lot of experience of the both approaches when writing an RPG game in Java. Originally I wrote the whole game using class-based OOP, but eventually realised that this was the wrong approach (it was becoming unmaintainable as the class hierarchy expanded). I therefore converted the whole code base to prototype-based code. The result was much better and easier to manage.

Source code here if you are interested (Tyrant - Java Roguelike)

Here are the main benefits:

It's trivial to create new "classes" - just copy the prototype and change a couple of properties and voila... new class. I used this to define new type of potion for example in 3-6 lines of Java each. Much better than a new class file and loads of boilerplate!

- just copy the prototype and change a couple of properties and voila... new class. I used this to define new type of potion for example in 3-6 lines of Java each. Much better than a new class file and loads of boilerplate! It's possible to build and maintain extremely large numbers of "classes" with comparatively little code - Tyrant for example had something like 3000 different prototypes with only about 42,000 lines of code total. That's pretty amazing for Java!

- Tyrant for example had something like 3000 different prototypes with only about 42,000 lines of code total. That's pretty amazing for Java! Multiple inheritance is easy - you just copy a subset of the properties from one prototype and paste them over the properties in another prototype. In an RPG for example, you might want a "steel golem" to have some of the properties of a "steel object" and some of the properties of a "golem" and some of the properties of an "unintelligent monster". Easy with prototypes, try doing that with an inheritance heirarchy......

- you just copy a subset of the properties from one prototype and paste them over the properties in another prototype. In an RPG for example, you might want a "steel golem" to have some of the properties of a "steel object" and some of the properties of a "golem" and some of the properties of an "unintelligent monster". Easy with prototypes, try doing that with an inheritance heirarchy...... You can do clever things with property modifiers - by putting clever logic in the generic "read property" method, you can implement various modifiers. For example, it was easy to define a magic ring that added +2 strength to whoever was wearing it. The logic for this was in the ring object, not in the "read strength" method, so you avoided having to put lots of conditional tests elsewhere in your code base (e.g. "is the character wearing a ring of strength increase?")

- by putting clever logic in the generic "read property" method, you can implement various modifiers. For example, it was easy to define a magic ring that added +2 strength to whoever was wearing it. The logic for this was in the ring object, not in the "read strength" method, so you avoided having to put lots of conditional tests elsewhere in your code base (e.g. "is the character wearing a ring of strength increase?") Instances can become templates for other instances - e.g. if you want to "clone" an object it is easy, just use the existing object as the prototype for the new object. No need to write lots of complex cloning logic for different classes.

- e.g. if you want to "clone" an object it is easy, just use the existing object as the prototype for the new object. No need to write lots of complex cloning logic for different classes. It's quite easy to change behaviour at runtime - i.e. you can change an properties and "morph" an object pretty much arbitrarily at runtime. Allows for cool in-game effects, and if you couple this with a "scripting language" then pretty much anything is possible at runtime.

- i.e. you can change an properties and "morph" an object pretty much arbitrarily at runtime. Allows for cool in-game effects, and if you couple this with a "scripting language" then pretty much anything is possible at runtime. It's more suited to a "functional" style of programming - you tend to find yourself writing lots of functions that analyse objects an act appropriately, rather than embedded logic in methods attached to specific classes. I personally prefer this FP style.

Here are the main drawbacks:

You lose the assurances of static typing - since you are effectively creating a dynamic object system. This tends to mean that you need to write more tests to ensure behaviour is correct and that objects are of the right "kind"

- since you are effectively creating a dynamic object system. This tends to mean that you need to write more tests to ensure behaviour is correct and that objects are of the right "kind" There is some performance overhead - since reads of object properties are generally forced to go through one or more map lookups, you pay a slight cost in terms of performance. In my case it wasn't a problem, but it could be an issue in some cases (e.g. a 3D FPS with a lot of objects being queried in every frame)

- since reads of object properties are generally forced to go through one or more map lookups, you pay a slight cost in terms of performance. In my case it wasn't a problem, but it could be an issue in some cases (e.g. a 3D FPS with a lot of objects being queried in every frame) Refactorings don't work the same way - in a prototype based system you are essentially "building" your inheritance heirarchy with code. IDEs / refactoring tools can't really help you since they can't grok your approach. I never found this a problem, but it could get out of hand if you are not careful. You probably want tests to check that your inheritance hierarchy is being constructed correctly!

- in a prototype based system you are essentially "building" your inheritance heirarchy with code. IDEs / refactoring tools can't really help you since they can't grok your approach. I never found this a problem, but it could get out of hand if you are not careful. You probably want tests to check that your inheritance hierarchy is being constructed correctly! It's a bit alien - people used to a conventional OOP style may easily get confused. "What do you mean there's only one class called "Thing"?!?" - "How do I extend this final Thing class!?!" - "You are violating OOP principles!!!" - "It's wrong to have all these static functions that act on any kind of object!?!?"

Finally some implementation notes: