Most times, you should extend. When you have some functionality that is
useful and then you can make another thing that has the same properties plus
some others, you should extend. Request on its own is a fine class and I use
it all the time. Request.HTML adds some additional behavior to the class to
handle a specific kind of response, while Request.JSON does the same thing
for a different kind of response. Both of these subclasses still use all the
functionality in Request, but the extra stuff they add (HTML and JSON
response handling) is unique; i.e. the JSON version doesn't need any of the
stuff in the HTML version and vice versa.
Now consider Spinner's integration with Request. We could use .implement to
overwrite the default behavior of Request and, in so doing, we would alter
all of the subclasses of Request. For instance, let's say that in our web
app we want all the request instances to have an app-specific header, we
could implement that into the options:
Request.implement({
options: {
headers: {
appName: 'foo'
}
}
});
Now ALL the request instances, be they Request, Request.JSON, Request.HTML,
or some other subclass, they'll all get this header by default.
Unfortunately, if you want to alter a function, rather than alter an option
like this, you would have to overwrite the function entirely. This is a very
inconvenient way to patch things; duplicating their functions so you can
inject some small tweak.
We could subclass it, but then we'd have to subclass all of
them: Request.Spinner, Request.HTML.Spinner, Request.JSON.Spinner, etc. The
downside here is that you have to subclass every one of these and, if you
were to introduce a new type of Request subclass, you'd have to subclass it,
too, and if the Spinner logic in Spinner.js is in a closure, you'd have to
duplicate it.
Refactor lets you extend a class onto itself, essentially (unlike extending,
where you get this.parent(), with refactor, you get this.previous) . It's a
bit hacky, and we don't use it a lot. But it does allow for some nice
integration into existing classes. Spinner is one example. The only place
where we use it in -more is the HtmlTable classes and URI. URI uses refactor
to add more functionality to the URI codebase. It's stuff that you don't
normally need, so it's separate.
For HtmlTable, what we have is a mix-and-match of functionalities that you
can use in any combination. You can use HtmlTable on its own, or HtmlTable +
Zebra. Or HtmlTable + Select. Or HtmlTable + Zebra + Select. Or HtmlTable +
Select + Sort. Or just HtmlTable + Sort. Etc. Because there are all these
combinations, extending doesn't work. You'd need to make an extension for
every combination. If I went back and rewrote the HtmlTable stuff, I'd
probably use a plugin-style pattern, but using Refactor works fine, too.
I tend to use Refactor in my own code rarely. Typically to alter a class to
behave in a specific way for my environment. For Cloudera's HUE desktop, we
refactor Request so that all the Request classes and subclasses do some
extra work on send and receive. But, again, it's rather rare.
Aaron
On Tue, Aug 31, 2010 at 1:30 PM, Rolf -nl <[email protected]> wrote:
> I have read both the docs and the posts on clientcide, plus the
> mootools more source, but I'm still not 100% sure about this..
>
> Before, I was extending classes, classes from myself, classes from -
> More, classes from others (e.g. forge/github) to add some extra
> functionality I needed, overwriting existing methods and adding new
> ones. Looking back I could probably have used Refactor as well... I
> think....
>
> In -More I see more Refactor used in HtmlTable for example, where it
> adds a little bit extra with each change (zebra, sort, etc.)
> With the Fx there's usually Extends. From what I understand it has to
> do with not destroying the namespace, but that's still a little vague
> to me.
> Could you say that if there's no subclass then you don't need Extend?
> Or, use Extend if you change actual functionality of class A to B
> (like Fx.Morph becoming a move thing with Fx.Move)? With Refactor it
> seems like its meant to be used when adding small extra bits but not
> changing the original functionality of a class.. (makes sense?)
>
> For example, Request is Refactored with Spinner functionality.. in
> theory you could also extend Request to implement/add Spinner (no?),
> but because it's only a small addition you refactor it.. or am I
> thinking wrong?
>
>
>
> (btw- I feel like I'm flooding the google group with too many posts,
> but that's just because I have a "Moo" moment currently and I'm trying
> to understand Git at the same time, while in fact I should be doing
> beziers in Illustrator. But anyway, I hope to help out some others as
> well too soon)
>