Задача: ООП на javascript: классы, наследование, инкапсуляция
Исходник: Наследование и инкапсуляция, реализация с помощью базового класса Class, язык: javascript [code #552, hits: 8645]
автор: - [добавлен: 19.12.2007]
  1. // Базовый класс
  2. function Class(bc,c,i)
  3. {
  4. var l=function(){};
  5. l.prototype=bc.prototype;
  6. var cc=c;
  7. cc.base=new l();
  8. cc.prototype=new l();
  9. i.call( cc.prototype );
  10. cc.prototype.constructor=cc;
  11. return cc;
  12. }
  13.  
  14. // Пример расширения
  15. var MyClass = Class(
  16. //Base class
  17. BaseClass,
  18. //Constructor
  19. function( a, b )
  20. {
  21. base.constructor.call( this );
  22. this.a = a;
  23. this.b = b;
  24. },
  25. //Implementation
  26. function()
  27. {
  28.  
  29. this.someMethod = function( a )
  30. {
  31. // call method from base class;
  32. return base.someMethod.call( this, a );
  33. }
  34.  
  35. this.callPrivate = function()
  36. {
  37. // call private method
  38. privateMethod.call( this );
  39. }
  40.  
  41. // private method
  42. var privateMethod = function()
  43. {
  44. return this.a + this.b;
  45. }
  46.  
  47. }
  48. );
  49.  
  50. // Использование
  51. var obj = new MyClass( 1, 2 );
  52.  
  53. obj.someMethod();
  54. obj.callPrivate(); // вернет 1+2 переданные в конструкторе
  55.  
  56. // obj.privateMethod(); - даст ошибку
Вводится базовый класс Class, от которого по определенным правилам расширяются все остальные.

Делается промежуточный объект "l" и потом и в прототип и в ссылку на базововый делается "new l()" (так что new все равно есть, он нужен для того чтобы ссылки на прототипы развязать, если этого не сделать то при изменении прототипа нового класса будет изменятся прототип базового), к тому же поэтому конструктор базового класса при объявлении типа не вызывается, а в коде выше вся пляска вокруг preparing нужна только для того чтобы не вызывать базовый конструктор, это выглядит некрасиво , к тому же правильней из наследуемого класса вызывать конструктор базового руками а не так как выше (автоматически), ведь может быть что аргументы при наследовании меняются и перед вызовом их надо скорректировать, переставить местами или еще чего... (в CPP он конечно автоматически вызывается но этот вызов можно корректировать, и здесь никак, поэтому мое решение — вызывать из конструктора насильно)

Источник: http://rsdn.ru/Forum/message/2014890.flat.aspx
Тестировалось на: IE 6.0 SP2, Mozilla FF 1.5, Opera 9.0

+добавить реализацию