<?xml version="1.0" encoding="UTF-8"?><!-- generator="wordpress/2.2.1" -->
<rss version="2.0" 
	xmlns:content="http://purl.org/rss/1.0/modules/content/">
<channel>
	<title>Комментарии на запись: ООП в Java Script (4): Наследование классов</title>
	<link>http://karaboz.ru/2007/10/06/oop-v-java-script-4-nasledovanie-klassov/</link>
	<description></description>
	<pubDate>Thu, 09 Sep 2010 01:51:54 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.2.1</generator>

	<item>
		<title>От: утко</title>
		<link>http://karaboz.ru/2007/10/06/oop-v-java-script-4-nasledovanie-klassov/#comment-823</link>
		<author>утко</author>
		<pubDate>Fri, 19 Feb 2010 00:06:47 +0000</pubDate>
		<guid>http://karaboz.ru/2007/10/06/oop-v-java-script-4-nasledovanie-klassov/#comment-823</guid>
		<description>Спасибо за статью, очень подробная.
Хотя после столь полного разъяснения, приведенные модифицирования сможет реализовать каждый, но возможно кому то пригодится.

Как не терять прототип объявленный у дочернего класса до наследования:
[code]
Function.prototype.inheritsFrom = function(superClass) {
	var protot = this.prototype;
	var Inheritance = function(){};
	Inheritance.prototype = superClass.prototype;

	this.prototype = new Inheritance();
	this.prototype.constructor = this;
	this.superClass = superClass;

	for (var key in protot) this.prototype[key] = protot[key];
}

class1 = function () {}
class1.prototype = {
	m : 0
}

class2 = function () {}
class2.prototype = {
	m1 : 1
}

class2.inheritsFrom(class1);

alert(new class2().m1)

[/code]</description>
		<content:encoded><![CDATA[<p>Спасибо за статью, очень подробная.<br />
Хотя после столь полного разъяснения, приведенные модифицирования сможет реализовать каждый, но возможно кому то пригодится.</p>
<p>Как не терять прототип объявленный у дочернего класса до наследования:<br />
[code]<br />
Function.prototype.inheritsFrom = function(superClass) {<br />
	var protot = this.prototype;<br />
	var Inheritance = function(){};<br />
	Inheritance.prototype = superClass.prototype;</p>
<p>	this.prototype = new Inheritance();<br />
	this.prototype.constructor = this;<br />
	this.superClass = superClass;</p>
<p>	for (var key in protot) this.prototype[key] = protot[key];<br />
}</p>
<p>class1 = function () {}<br />
class1.prototype = {<br />
	m : 0<br />
}</p>
<p>class2 = function () {}<br />
class2.prototype = {<br />
	m1 : 1<br />
}</p>
<p>class2.inheritsFrom(class1);</p>
<p>alert(new class2().m1)</p>
<p>[/code]</p>
]]></content:encoded>
	</item>
	<item>
		<title>От: feedbee</title>
		<link>http://karaboz.ru/2007/10/06/oop-v-java-script-4-nasledovanie-klassov/#comment-534</link>
		<author>feedbee</author>
		<pubDate>Thu, 02 Jul 2009 08:26:45 +0000</pubDate>
		<guid>http://karaboz.ru/2007/10/06/oop-v-java-script-4-nasledovanie-klassov/#comment-534</guid>
		<description>Одновременно проверим, что методы надкласса &#62;&#62;отсались&#62;лирическре&#62;посиупим</description>
		<content:encoded><![CDATA[<p>Одновременно проверим, что методы надкласса &gt;&gt;отсались&gt;лирическре&gt;посиупим</p>
]]></content:encoded>
	</item>
	<item>
		<title>От: Pavel Volodko</title>
		<link>http://karaboz.ru/2007/10/06/oop-v-java-script-4-nasledovanie-klassov/#comment-377</link>
		<author>Pavel Volodko</author>
		<pubDate>Tue, 03 Mar 2009 11:44:40 +0000</pubDate>
		<guid>http://karaboz.ru/2007/10/06/oop-v-java-script-4-nasledovanie-klassov/#comment-377</guid>
		<description>To Фёдор:
Таки "решил" и, стало быть, "написал".
Звиняйте за опечатку.</description>
		<content:encoded><![CDATA[<p>To Фёдор:<br />
Таки &#034;решил&#034; и, стало быть, &#034;написал&#034;.<br />
Звиняйте за опечатку.</p>
]]></content:encoded>
	</item>
	<item>
		<title>От: Федор</title>
		<link>http://karaboz.ru/2007/10/06/oop-v-java-script-4-nasledovanie-klassov/#comment-376</link>
		<author>Федор</author>
		<pubDate>Mon, 02 Mar 2009 22:51:26 +0000</pubDate>
		<guid>http://karaboz.ru/2007/10/06/oop-v-java-script-4-nasledovanie-klassov/#comment-376</guid>
		<description>&#62;&#62; Pavel Volodko: [...] вот, решил тоже написал [...]

Дык "решил" или "написал"?
Дай-ка и я напишу...</description>
		<content:encoded><![CDATA[<p>&gt;&gt; Pavel Volodko: [&#8230;] вот, решил тоже написал [&#8230;]</p>
<p>Дык &#034;решил&#034; или &#034;написал&#034;?<br />
Дай-ка и я напишу&#8230;</p>
]]></content:encoded>
	</item>
	<item>
		<title>От: Pavel Volodko</title>
		<link>http://karaboz.ru/2007/10/06/oop-v-java-script-4-nasledovanie-klassov/#comment-375</link>
		<author>Pavel Volodko</author>
		<pubDate>Mon, 02 Mar 2009 17:48:35 +0000</pubDate>
		<guid>http://karaboz.ru/2007/10/06/oop-v-java-script-4-nasledovanie-klassov/#comment-375</guid>
		<description>Объёмный труд :-) Почитал с интересом и обнаружил много общего со своими идеями.
Если интересно - вот, решил тоже написал статью на эту тему: &lt;a href="http://web-dev-ru.blogspot.com/2009/02/javascript.html" rel="nofollow"&gt;Классическое наследование в JavaScript&lt;/a&gt;. Не так детально, конечно, но надеюсь более менее понятно.</description>
		<content:encoded><![CDATA[<p>Объёмный труд :-) Почитал с интересом и обнаружил много общего со своими идеями.<br />
Если интересно - вот, решил тоже написал статью на эту тему: <a href="http://web-dev-ru.blogspot.com/2009/02/javascript.html" rel="nofollow">Классическое наследование в JavaScript</a>. Не так детально, конечно, но надеюсь более менее понятно.</p>
]]></content:encoded>
	</item>
	<item>
		<title>От: black</title>
		<link>http://karaboz.ru/2007/10/06/oop-v-java-script-4-nasledovanie-klassov/#comment-61</link>
		<author>black</author>
		<pubDate>Tue, 25 Dec 2007 16:53:43 +0000</pubDate>
		<guid>http://karaboz.ru/2007/10/06/oop-v-java-script-4-nasledovanie-klassov/#comment-61</guid>
		<description>Видим, что подкласс унаследовал метод .method своего надкласса (выполняет его, как свой собственный). Как это происходит? Сначала интерпретатор ищет метод .method в самом объекте objSub и естественно не находит его там. 
---begin emphatic
 Далее, интерпретатор обращается к ClassSub.prototype и ищет .method среди свойств этого объекта. Опять же — ничего не находит: мы нигде не задавали ничего похожего на ClassSub.prototype.method = function(){}. 
---end emphatic
Но ведь сам объект ClassSub.prototype создан из функции-конструтора Class().
--- begin emphatic
 Поэтому, не найдя нужных свойств в самом ClassSub.prototype,  
--- end emphatic
интерпретатор обращается к .prototype функции-конструтора этого объекта. И уже здесь находит запрашиваемый метод: Class.prototype.method = function(){}.

Мне режет слух данная формулировка поскольку из нее предполагается, что после того как вы выполнили присвоение 
 Cat.prototype = new Animal(); // наследуем от класса Animal
у объекта Cat.prottype могли бы сохраниться ранее объявленные методы или свойства

Cat.prototype.boo = function () {alert ('boo');}
Cat.prototype = new Animal(); // наследуем от класса Animal
 .....
cat_thing.boo ();// как и ожидалось не работает

-- может это как-то переформулировать ?</description>
		<content:encoded><![CDATA[<p>Видим, что подкласс унаследовал метод .method своего надкласса (выполняет его, как свой собственный). Как это происходит? Сначала интерпретатор ищет метод .method в самом объекте objSub и естественно не находит его там.<br />
&#8212;begin emphatic<br />
 Далее, интерпретатор обращается к ClassSub.prototype и ищет .method среди свойств этого объекта. Опять же — ничего не находит: мы нигде не задавали ничего похожего на ClassSub.prototype.method = function(){}.<br />
&#8212;end emphatic<br />
Но ведь сам объект ClassSub.prototype создан из функции-конструтора Class().<br />
&#8212; begin emphatic<br />
 Поэтому, не найдя нужных свойств в самом ClassSub.prototype,<br />
&#8212; end emphatic<br />
интерпретатор обращается к .prototype функции-конструтора этого объекта. И уже здесь находит запрашиваемый метод: Class.prototype.method = function(){}.</p>
<p>Мне режет слух данная формулировка поскольку из нее предполагается, что после того как вы выполнили присвоение<br />
 Cat.prototype = new Animal(); // наследуем от класса Animal<br />
у объекта Cat.prottype могли бы сохраниться ранее объявленные методы или свойства</p>
<p>Cat.prototype.boo = function () {alert (&#039;boo&#039;);}<br />
Cat.prototype = new Animal(); // наследуем от класса Animal<br />
 &#8230;..<br />
cat_thing.boo ();// как и ожидалось не работает</p>
<p>&#8211; может это как-то переформулировать ?</p>
]]></content:encoded>
	</item>
	<item>
		<title>От: Dmitry A. Soshnikov</title>
		<link>http://karaboz.ru/2007/10/06/oop-v-java-script-4-nasledovanie-klassov/#comment-59</link>
		<author>Dmitry A. Soshnikov</author>
		<pubDate>Wed, 19 Dec 2007 09:27:50 +0000</pubDate>
		<guid>http://karaboz.ru/2007/10/06/oop-v-java-script-4-nasledovanie-klassov/#comment-59</guid>
		<description>Да, вторым вариантом может являеться рекурсивный вызов родительских конструкторов при эплае дочерних, такми образом вручную их (родительские конструкторы) вызывать не надо. Моя реализация несколько другая, но все же приведу ее, чтобы показать еще один способ решения той проблемы:

&lt;pre&gt;
function Class(params) {

  var Class = function oopClass() {
    // вот здесь вызовятся рекурсивно все конструкторы в нужном порядке
    if (this.__construct) {
      var t = this; var a = arguments; var __construrct;
      (__construrct = function(class) {
        if (class) {
          __construrct(class.__parent);
          class.__constructor.apply(t, a);
        }
      })(this);
    }
  }
   
   // здесь ниже определение наследования, если нужно,
   // запись в Class.prototype.__constructor = params.__constructor,
   // Class.prototype.__destructor = params.__destructor,
   // Class.prototype.__parent = params.__extends (если надо),
   // и т.д.

  return Class;

}

// создание "класса" Widget

var Widget = Class({
  __constructor: function(obj) {
    if (obj) {
      for (var k in obj) {
        this[k] = obj[k];
      }
    }
    !this.data &#38;&#38; (this.data = {});
    //alert('Widget constructor');
  },
  __destructor: function() {
    alert('Widget destructor');
  }
});

// какие-то методы Widget'a

Widget.prototype.setValue = function(value) {
  this.data.value = value;
}

Widget.prototype.getValue = function() {
  alert(this.data.value);
}

Widget.prototype.getParentObj = function() {
  if (!this.__parent) {
    return null;
  }
  return this.__parent;
}

// создание "класса" WidgetRoot, наследуемого от Widget

var WidgetRoot = Class({
  __extends: Widget,
  __constructor: function(_obj) {
    //alert('WidgetRoot constructor');
  },
  __destructor: function() {
    alert('WidgetRoot destructor');
  }
});

// переопределение метода родительского "класса"

WidgetRoot.prototype.getValue = function() {
  alert(this.data.value + ' from WidgetRoot');
}

// а здесь уже объект "класса" WidgetRoot

var wr = new WidgetRoot({a: 2, b: 3});
wr.setValue(10);
wr.getValue(); // свой (переопределенный) метод
wr.__parent.getValue.call(wt); // вызов родительского
&lt;/pre&gt;</description>
		<content:encoded><![CDATA[<p>Да, вторым вариантом может являеться рекурсивный вызов родительских конструкторов при эплае дочерних, такми образом вручную их (родительские конструкторы) вызывать не надо. Моя реализация несколько другая, но все же приведу ее, чтобы показать еще один способ решения той проблемы:</p>
<pre>
function Class(params) {

  var Class = function oopClass() {
    // вот здесь вызовятся рекурсивно все конструкторы в нужном порядке
    if (this.__construct) {
      var t = this; var a = arguments; var __construrct;
      (__construrct = function(class) {
        if (class) {
          __construrct(class.__parent);
          class.__constructor.apply(t, a);
        }
      })(this);
    }
  }

   // здесь ниже определение наследования, если нужно,
   // запись в Class.prototype.__constructor = params.__constructor,
   // Class.prototype.__destructor = params.__destructor,
   // Class.prototype.__parent = params.__extends (если надо),
   // и т.д.

  return Class;

}

// создание "класса" Widget

var Widget = Class({
  __constructor: function(obj) {
    if (obj) {
      for (var k in obj) {
        this[k] = obj[k];
      }
    }
    !this.data &amp;&amp; (this.data = {});
    //alert('Widget constructor');
  },
  __destructor: function() {
    alert('Widget destructor');
  }
});

// какие-то методы Widget'a

Widget.prototype.setValue = function(value) {
  this.data.value = value;
}

Widget.prototype.getValue = function() {
  alert(this.data.value);
}

Widget.prototype.getParentObj = function() {
  if (!this.__parent) {
    return null;
  }
  return this.__parent;
}

// создание "класса" WidgetRoot, наследуемого от Widget

var WidgetRoot = Class({
  __extends: Widget,
  __constructor: function(_obj) {
    //alert('WidgetRoot constructor');
  },
  __destructor: function() {
    alert('WidgetRoot destructor');
  }
});

// переопределение метода родительского "класса"

WidgetRoot.prototype.getValue = function() {
  alert(this.data.value + ' from WidgetRoot');
}

// а здесь уже объект "класса" WidgetRoot

var wr = new WidgetRoot({a: 2, b: 3});
wr.setValue(10);
wr.getValue(); // свой (переопределенный) метод
wr.__parent.getValue.call(wt); // вызов родительского
</pre>
]]></content:encoded>
	</item>
	<item>
		<title>От: karaboz</title>
		<link>http://karaboz.ru/2007/10/06/oop-v-java-script-4-nasledovanie-klassov/#comment-54</link>
		<author>karaboz</author>
		<pubDate>Thu, 13 Dec 2007 02:36:31 +0000</pubDate>
		<guid>http://karaboz.ru/2007/10/06/oop-v-java-script-4-nasledovanie-klassov/#comment-54</guid>
		<description>О боже! какую чудовищную ошибку я совершил! =(( Видимо я так увлекся идеей, что "если JS не находит метода в самом объекте, то он ищет его в прототипе функции-конструктора этого объекта", что допустил идиотский ляп в самом важном месте (=  

Я хотел хранить ссылку на .superClass в .prototype.superClass функции-конструктора подкласса:
&lt;pre&gt;this.prototype.superClass = superClass;&lt;/pre&gt;

Потом, пользуясь свойством прототипов, я хотел ловко подцеплять эту ссылку при конструировании объекта подкласса, во время вызовов new ClassSub():
&lt;pre&gt;this.SuperClass.apply(this, arguments);&lt;/pre&gt;

Но ведь это же очевидно, что когда мы начинаем вызывать подкласс самого подкласса: new ClassSubSub(), то при входе в функцию-конструктор подкласса (ClassSub), слово this ссылается не на этот подкласс, а на ClassSubSub (т.к. мы применяем функцию apply)! И получается бесконечный вызов ClassSubSub самого себя! Черт.

Вот как надо делать по-честному:
&lt;pre&gt;
// Универсальная функция наследования
Function.prototype.inheritsFrom = function(superClass) {
	var Inheritance = function(){};
	Inheritance.prototype = superClass.prototype;

	this.prototype = new Inheritance();
	this.prototype.constructor = this;
	&lt;strike&gt;this.prototype.superClass = superClass;&lt;/strike&gt;
	this.superClass = superClass;
}

// функция-конструктор класса
var Class = function(){}

// описание свойств и методов класса
Class.prototype.method = function(){};

// функция-конструктор подкласса
var ClassSub = function(){
	&lt;strike&gt;this.superClass.apply(this, arguments);&lt;/strike&gt;
	ClassSub.superClass.apply(this, arguments);
}
// определение наследования
ClassSub.inheritsFrom(Class); // sic!

// описание свойств и методов подкласса
ClassSub.prototype.method = function(){ 
	&lt;strike&gt;this.superClass.prototype.method.apply(this, arguments);&lt;/strike&gt;
	ClassSub.superClass.prototype.method.apply(this, arguments);
}
&lt;/pre&gt;

&lt;strong&gt;Dmitry A. Soshnikov!&lt;/strong&gt; Большое вам спасибо, что указали мне на эту досадную ошибку! Теперь наследовать можно до бесконечности (= (&lt;strong&gt;Михайлов Денис&lt;/strong&gt;, приношу вам свои извинения)

p.s. в статье я испраил весь код в сотвествие с вышеизложенным рассуждением</description>
		<content:encoded><![CDATA[<p>О боже! какую чудовищную ошибку я совершил! =(( Видимо я так увлекся идеей, что &#034;если JS не находит метода в самом объекте, то он ищет его в прототипе функции-конструктора этого объекта&#034;, что допустил идиотский ляп в самом важном месте (=  </p>
<p>Я хотел хранить ссылку на .superClass в .prototype.superClass функции-конструктора подкласса:</p>
<pre>this.prototype.superClass = superClass;</pre>
<p>Потом, пользуясь свойством прототипов, я хотел ловко подцеплять эту ссылку при конструировании объекта подкласса, во время вызовов new ClassSub():</p>
<pre>this.SuperClass.apply(this, arguments);</pre>
<p>Но ведь это же очевидно, что когда мы начинаем вызывать подкласс самого подкласса: new ClassSubSub(), то при входе в функцию-конструктор подкласса (ClassSub), слово this ссылается не на этот подкласс, а на ClassSubSub (т.к. мы применяем функцию apply)! И получается бесконечный вызов ClassSubSub самого себя! Черт.</p>
<p>Вот как надо делать по-честному:</p>
<pre>
// Универсальная функция наследования
Function.prototype.inheritsFrom = function(superClass) {
	var Inheritance = function(){};
	Inheritance.prototype = superClass.prototype;

	this.prototype = new Inheritance();
	this.prototype.constructor = this;
	<strike>this.prototype.superClass = superClass;</strike>
	this.superClass = superClass;
}

// функция-конструктор класса
var Class = function(){}

// описание свойств и методов класса
Class.prototype.method = function(){};

// функция-конструктор подкласса
var ClassSub = function(){
	<strike>this.superClass.apply(this, arguments);</strike>
	ClassSub.superClass.apply(this, arguments);
}
// определение наследования
ClassSub.inheritsFrom(Class); // sic!

// описание свойств и методов подкласса
ClassSub.prototype.method = function(){
	<strike>this.superClass.prototype.method.apply(this, arguments);</strike>
	ClassSub.superClass.prototype.method.apply(this, arguments);
}
</pre>
<p><strong>Dmitry A. Soshnikov!</strong> Большое вам спасибо, что указали мне на эту досадную ошибку! Теперь наследовать можно до бесконечности (= (<strong>Михайлов Денис</strong>, приношу вам свои извинения)</p>
<p>p.s. в статье я испраил весь код в сотвествие с вышеизложенным рассуждением</p>
]]></content:encoded>
	</item>
	<item>
		<title>От: Dmitry A. Soshnikov</title>
		<link>http://karaboz.ru/2007/10/06/oop-v-java-script-4-nasledovanie-klassov/#comment-52</link>
		<author>Dmitry A. Soshnikov</author>
		<pubDate>Tue, 11 Dec 2007 15:25:04 +0000</pubDate>
		<guid>http://karaboz.ru/2007/10/06/oop-v-java-script-4-nasledovanie-klassov/#comment-52</guid>
		<description>Вернее даже так: создавать объекты третьего уровеня и ниже можно (и даже методы родительских уровней будут работать), но нельзя, начиная с третьего уровня, вызвать родительские конструкторы в контексте дочерних.</description>
		<content:encoded><![CDATA[<p>Вернее даже так: создавать объекты третьего уровеня и ниже можно (и даже методы родительских уровней будут работать), но нельзя, начиная с третьего уровня, вызвать родительские конструкторы в контексте дочерних.</p>
]]></content:encoded>
	</item>
	<item>
		<title>От: Dmitry A. Soshnikov</title>
		<link>http://karaboz.ru/2007/10/06/oop-v-java-script-4-nasledovanie-klassov/#comment-51</link>
		<author>Dmitry A. Soshnikov</author>
		<pubDate>Tue, 11 Dec 2007 15:15:22 +0000</pubDate>
		<guid>http://karaboz.ru/2007/10/06/oop-v-java-script-4-nasledovanie-klassov/#comment-51</guid>
		<description>Вот, вдагонку, полностью (НЕ)работающий код:
&lt;pre&gt;
// Универсальная функция наследования
Function.prototype.inheritsFrom = function(superClass) {
	var Inheritance = function(){};
	Inheritance.prototype = superClass.prototype;
	this.prototype = new Inheritance();
	this.prototype.constructor = this;
	this.prototype.superClass = superClass;
}

// функция-конструктор Class
var Class = function(data) {
	this.data = data &#124;&#124; {};
	alert('Class');
}

// функция-конструктор ClassSub
var ClassSub = function() {
	this.superClass.apply(this, arguments);
	alert('ClassSub');
}
// определение наследования
ClassSub.inheritsFrom(Class); // sic!

// функция-конструктор ClassSubSub
var ClassSubSub = function() {
	this.superClass.apply(this, arguments);
	alert('ClassSubSub');
}

ClassSubSub.inheritsFrom(ClassSub); // sic!

var c = new ClassSubSub({a: 1, b: 3});
&lt;pre&gt;</description>
		<content:encoded><![CDATA[<p>Вот, вдагонку, полностью (НЕ)работающий код:</p>
<pre>
// Универсальная функция наследования
Function.prototype.inheritsFrom = function(superClass) {
	var Inheritance = function(){};
	Inheritance.prototype = superClass.prototype;
	this.prototype = new Inheritance();
	this.prototype.constructor = this;
	this.prototype.superClass = superClass;
}

// функция-конструктор Class
var Class = function(data) {
	this.data = data || {};
	alert('Class');
}

// функция-конструктор ClassSub
var ClassSub = function() {
	this.superClass.apply(this, arguments);
	alert('ClassSub');
}
// определение наследования
ClassSub.inheritsFrom(Class); // sic!

// функция-конструктор ClassSubSub
var ClassSubSub = function() {
	this.superClass.apply(this, arguments);
	alert('ClassSubSub');
}

ClassSubSub.inheritsFrom(ClassSub); // sic!

var c = new ClassSubSub({a: 1, b: 3});
</pre>
<pre></pre>
]]></content:encoded>
	</item>
</channel>
</rss>
