Exposes Class Mutator

Valerio came up quite a time ago with another class mutator called Exposes. (I already wrote a post about the Binds mutator a few posts ago). I rewrote the mutator a way I think the usage is cleaner.

The Exposes mutator is about getters and setters, which means its incompatible with IE and reduces it's practical use to internal websites, experimental use, or AIR apps. The mutator converts methods named like getFoo to getters and setFoo to setters. That is myObj.foo = "bar" calls the setter and alert(myObj.foo); the getter. Note that this means you can't store the property internally under the same name, as setting the property with this.foo = newFoo; in the setter calls the setter again, which results in an endless recursion. The same is true for getters. (MDC about getters and setters)

The mutator:

  1. Class.Mutators.Exposes = function(self, exposes){
  2. if (!exposes) return;
  3. for (method in self) {
  4. var match = method.match(/^(get|set)([A-Z])(\w*)$/);
  5. if (match) {
  6. var prop = match[2].toLowerCase() + match[3];
  7. self[(match[1] == 'get') ? '__defineGetter__' :
  8. '__defineSetter__'](prop, self[method]);
  9. }
  10. }
  11. };
The mutator iterates over all attributes and if one begins with set or get followed by an uppercase letter it sets it as an attribute setter or getter respectively using __defineGetter__ and __defineSetter__.

A slightly more complex Exposes mutator which accepts a list of attributes to convert is available here.

To see the usage I'll make an example. Say we have a Person with a first, last and full name. The full name being a combination of the last and first name.
  1. var Person = new Class({
  2. Exposes: true,
  3.  
  4. initialize: function(first, last){
  5. if (!last) {
  6. // last name not given, first argument is the full name
  7. // using the setter to set the full name
  8. this.name = first;
  9. } else {
  10. this.first = first;
  11. this.last = last;
  12. }
  13. },
  14.  
  15. getName: function(){
  16. return this.first + " " + this.last;
  17. },
  18.  
  19. setName: function(name){
  20. name = name.split(' ');
  21. this.first = name[0];
  22. this.last = name[1];
  23. },
  24.  
  25. getInitials: function(){
  26. return this.first[0] + ". " + this.last[0] + ".";
  27. }
  28. });
The class should be pretty self explanatory. We can't just update the initials without changing the name, hence only a getter for initials.

With the Exposes mutator there is no need now to call the setter and getters by hand and we can just do things like:
  1. var me = new Person("Jahn Kassens");
  2. // oops, someone misspelled my first name, let's fix that
  3. me.first = "Jan";
  4. alert(me.name); // Jan Kassens
  5. alert(me.initials); // J. K.
  6.  
  7. var test = new Person("Max", "Mustermann");
  8. alert(test.name); // Max Mustermann
  9. test.name = "John Doe";
  10. alert(test.last) // Doe

2 Responses to Exposes Class Mutator

  1. 639 Hans Pinckaers 2008-10-07 09:19:46

    Pretty cool, sad it's not supported in IE, but I heard that it might be supported in IE8;)

  2. 2442 MooTools Class Mutators » Clientcide (Formerly CNET's Clientside) 2008-12-12 18:25:05

    ...the creation of private methods through closures.
    Update: Nathan points out that there’s also an Exposes mutator that Jan put together. This entry was posted on Thursday, December 11th, 2008 at 4:19 pm and is filed under ...

Leave a Reply