marionettejs/backbone.marionette — pull request #937 by jasonLaster (2014-02-25 03:37:00+00:00)
Title: Add support for extending className

#### Overview
It's fair to say that both inheritance and mixin view strategies are common and have their flaws. One of the problems with inheritance is that Backbone extend doesn't provide any help when properties collide.

Recently, we've been dealing with views whose class names collide. The two things we want are
+ a way to specify if a className should be extended
+ a hook for modifying how two classNames should be merged

---
#### Examples
In practice this looks like this:

```js
Overlay = Marionette.View.extend({
className: 'overlay-view',
constructor: function() {
this.extendClassName(Overlay.prototype);
Marionette.View.apply(this, arguments);
}
});

OverlayStatus = Overlay.extend({
className: 'status',
});

overlayStatus = new OverlayStatus();
overlayStatus->className(); // 'overlay-view status'
```

If extending child properties from a base class isn't your cup of tea, then this is for you:

```js
Overlay = Marionette.View.extend({
className: 'overlay-view'
});

OverlayStatus = Overlay.extend({
className: 'status',
initialize: function() {
this.extendClassName(Overlay.prototype);
}
});

overlayStatus = new OverlayStatus();
overlayStatus->className(); // 'overlay-view status'
```
#### Wins
What I like about this approach, is that it removes very common one off merge statements like `this.className = _.extend(Ovleray.prototype.className, this.className)` with something that is far more flexible going forward.

----
#### Subtle perks
These are pretty simple examples, so they skipped some nice wins that come with a more general solution.
+ `extendClassName` wraps the initial className property, so it's infinitely extenable
+ `mergeClassName` is invoked on the extended prototype, so each prototype can customize its merge strategy

----
This PR is based in part off of the discussion in #723. Curious to see what you guys think. Have you run into scenarios where this would break down?