Перейти из форума на сайт.

НовостиФайловые архивы
ПоискАктивные темыТоп лист
ПравилаКто в on-line?
Вход Забыли пароль? Первый раз на этом сайте? Регистрация
Компьютерный форум Ru.Board » Интернет » Web-программирование » Закладки » Наследование объектов в JavaScript.

Модерирует : Cheery

 Версия для печати • ПодписатьсяДобавить в закладки

Открыть новую тему     Написать ответ в эту тему

8AleX8



Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
JavaScript Object Inheritance

Цитата:
JavaScript's object oriented programming techniques are quite unique. This tutorial is an attempt to introduce you to OOP in JavaScript.  
 
Creating subclasses of a class is what makes object oriented programming so powerful. Unfortunately, JavaScript does not have full built-in support for the style of OOP that you may be accustomed to in Java, C#, or C++.
 
The biggest limitation that I ran into with JavaScript is the fact that there is no way to call a superclass method that has been overridden by a sub-class. I discovered a trick that provides this functionality. This tutorial will show the technique I use, but first we need to cover a little background on how to create objects and how to setup inheritance in JavaScript.  
 
...
 

Тем, кто хоть немного читает по англ. и чуть-чуть понимает принципы ООП, очень советую прочесть эту статью.
Если разберётесь не пожалеете.
Поделитесь впечатлениями....

Всего записей: 1813 | Зарегистр. 11-12-2001 | Отправлено: 22:12 10-02-2003 | Исправлено: 8AleX8, 09:01 14-02-2003
Vodmal



Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
8AleX8
Отличная статья. Я сам на днях искал что-либо по написанию классов на JavaScript, но ничего толкового не нашел. Пришлось самому на примерах (как и обычно) разбираться.
А тут такое пособие. Спасибо за ссылку!

Всего записей: 253 | Зарегистр. 03-09-2001 | Отправлено: 17:26 12-02-2003
Svarga

Moderator
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
8AleX8
Спасибо за статью !
Чуть посвежее голова будет-- или "поделюсь впечатлениями", или сделаю краткое резюме статьи на русском (может кому безанглоязычному сгодится).


----------
away.

Всего записей: 4161 | Зарегистр. 25-06-2002 | Отправлено: 02:20 13-02-2003
Svarga

Moderator
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
В общем, сделал перевод Если где что-то прогнал-- пишите, исправлю (особенно по терминологии-- напр., "superclass", "subclass" встречал только в английских оригиналах-- может в русских переводах принято употреблять какие-нибудь "суперклассы" с "субклассами" Само собой-- по пунктуации и орфографии).
 
Название cтатьи слишком глобальное-- правильнее было бы что-то вроде
"JavaScript: Проблема вызова метода родительского объекта"
 

Цитата:
Kevin Lindsey  

 
В JavaScript способы объективно ориентированного программирования довольно уникальны.  Эта статья-- попытка представить вам ООП в JavaScript.  
 
Мощь ООП заключена в возможности создания подклассов класса. К сожалению, JavaScript  не имеет встроенной поддержки ООП с которой вы возможно знакомы по Java, C# или  C++.
 
Главное ограничение, с которым я столкнулся в JavaScript-- это невозможность  вызова метода надкласса, перекрытого подклассом. Я нашёл способ, как обеспечить  такую функциональность. В этой статье раскрывается техника, которую я использую,  но сначала необходимо описать базовые принципы создания объектов и установления  порядка наследования в JavaScript.  
 
Для начала создадим новый JavaScript-объект, который послужит нам базовым классом.  Создание объекта в JavaScript состоит из двух операций. Сначала объявляется функция,  название которой станет названием нового объекта. Эту функцию обычно используют  в качестве  "конструктора ". Затем объявляется сам объект с помощью оператора   "new " и названия ранее объявленной функции с любыми параметрами, необходимыми  для инициализации объекта. Следующий код создаёт функцию Person ( "человек"),  а затем объект с помощью команды "new".

Код:
function Person(first, last) {
    this.first = first;
    this.last  = last;
// ам.англ. first name= имя, last name=фамилия
}
 
var person = new Person("Вася", "Пупкин");

Оператор "new" вызовет функцию с параметрами, заключёнными в выражении  "new". В контексте функции используется специальная переменная "this".  "This" обозначает текущий объект, с которым мы работаем. Использование  "this" позволяет добавлять объекту любые свойства и изменять их. Теперь нам необходимо добавить методы объекта, чтобы начать манипуляции над  новым объектом. Полезно будет создать метод "toString" каждому из наших   объектов для возможности их отображения в диалоговых окнах.

Код:
Person.prototype.toString() {
    return this.first + " " + this.last;
}
alert( person.toString() ); // результат-- "Вася Пупкин"
alert( person ); //  тот же результат, поскольку  alert  вызывает toString()

При создании функции мы создаём глобальное свойство, название которого совпадает с названием функции. Прежде всего мы обращаемся к глобальному свойству "Person", которое является на самом деле всего лишь конструктором.
Каждый объект JavaScript имеет свойство prototype. Именно это свойство делает  ООП возможным в JavaScript, однако это может показаться вам необычным, если вы  пришли в JavaScript из других обектно-ориентированных языков. Теперь о том, как  это работает. Когды мы обращаемся к свойству объекта, интерпретатор проверяет,  существует ли у объекта свойство с таким именем. Если оно отсутствует, интерпретатор  проверяет свойство prototype объекта, чтобы узнать, имеет ли объект, на который  указывает свойство prototype, искомое свойство. Если свойство не обнаружено, интерпретатор  проверяет, имеет ли, в свою очередь, свойство prototype свойство prototype. Если  имеет, то процесс будет продолжаться до тех пор, пока не найдется искомое свойство,  или же когда не останется больше свойств prototype для дальнейшего поиска.
 
Думаю, объект Person вполне устроит нас, но необхoдимо добавить больше информации  относительно данного человека ('person') с учётом того, что он является служащим  (employee). Создадим подклассы объекта Person.

Код:
Employee.prototype = new Person();
Employee.prototype.constructor = Employee;
Employee.superclass = Person.prototype;
 
function Employee(first, last, id) {
    // initialize properties here
}

Первая строка устанавливает последовательность наследования с помощью свойства  prototype. Если при поиске свойства у объекта Employee оно не найдено, интерпретатор  начнет обрабатывать последовательность prototype. Person будет первым объектом в последовательности благодаря первой строке.
 
Свойство constructor используется в скриптах для определения типа объекта.  Когда мы переопределили свойство prototype объекта Employee, также изменилось  свойство constructor на Person. Это и исправляется во второй строке.
 
Третья строка-- часть способа, который позволит вызывать методы надкласса,  спрятанные вследствие переопределения методов в подклассе, Об этом подробнее чуть  позже. Обратите внимание, что мы используем свойство class вместо prototype. Свойства  prototype здесь не отработают.
 
Если мы попытаемся использовать наш новый подкласс, обнаружится, что JavaScript  не позволяет вызвать метод constructor надкласса. Особенность проблемы заключается  в том, что мы хотим функцией-конструктором Person установить свойства "first"  и "last", в то время как функция Employee должна установить только свойство  "id". Я исправил скрипт: к сожалению код увеличился, однако он теперь  позволяет эффективно обращаться к конструктору надкласса. Поместим инициализирующий  код в новый метод, а затем вызовем метод из подкласса.

Код:
function Person(first, last) {
    if ( arguments.length > 0 )
        this.init(first, last);
}
 
Person.prototype.init = function(first, last) {
    this.first = first;
    this.last  = last;
}
 
Employee.prototype = new Person();
Employee.prototype.constructor = Employee;
Employee.superclass = Person.prototype;
 
function Employee(first, last, id) {
    if ( arguments.length > 0 ) {
        this.init(first, last);
        this.id = id;
    }
}

Возможно вы обратили внимание, что я добавил в конструкторы проверку того, передаются ли какие-либо аргументы. Мы устанавливаем последовательность наследования с помощью изменения значения свойства prototype содаваемого обїекта. В целях inherticance нам не нужна инициализация объекта. Она нужна только для его свойства prototype. Объект используется для наследования, когда ни одно свойство не передаётся конструктору. Это выглядит, как небольшая оптимизация (использование памяти и время выполнения), однако я обнаружил, что это практический подход в случаях, когда инициализация объекта даёт побочные эффекты. Например, инициализация объекта может вызвать изменение в SVG DOM, однако, если объект создаётся исключительно для наследования, вам может не понадобиться изменение DOM.
 
Когда мы создаём новый объект Person, его конструктор передаёт два аргумента методу объекта init, который затем инициализирует свойства объекта.
 
При создании объекта Employee, его конструктор вызывает метод объекта init. Поскольку для объекта Employee метод init не определён, интерпретатор движется далее по последовательности prototype. Следующий объект в последовательности-- это Person, поэтому вызывается метод init объекта Person, инициализирующий затем свойства объекта. Последняя строка конструктора Employee инициализирует свойство"id".
 
Мы создали новую проблему. Что произойдёт, если необходим подкласс для объекта Employee? Создадим объект Manager ("управляющий").

Код:
Manager.prototype = new Employee;
Manager.prototype.constructor = Manager;
Manager.superclass = Employee.prototype;
 
function Manager(first, last, id, department) {
    if ( arguments.length > 0 ) {
        this.init(first, last);
        this.department = department;
    }
}

Vы хотим, чтобы объект Person имел только свойства "first" и "last", объект Employee свойство "id", а объект Manager--  свойство "department" ("отдел"). При том, что имеем, этого никогда не случится: свойство id не присвоится никогда.
 
Давайте следовать логике, использовавшейся до этого. Создадим метод init для объекта Employee.

Код:
Employee.prototype = new Person();
Employee.prototype.constructor = Employee;
Employee.superclass = Person.prototype;
 
function Employee(first, last, id) {
    if ( arguments.length > 0 )
        this.init(first, last, id);
}
 
Employee.prototype.init = function(first, last, id) {
    //this.init(first, last); // Опа...бесконечная рекурсия
     this.id = id;
}
 
Manager.prototype = new Employee;
Manager.prototype.constructor = Manager;
Manager.superclass = Employee.prototype;
 
function Manager(first, last, id, department) {
    if ( arguments.length > 0 ) {
        this.init(first, last, id);
        this.department = department;
    }
}

Вот и проблема-- привызове метода init объектом Employee, интерпретатор найдет метод init, определённый для Employee. До этого метод init не был определён в Employee, поэтому интерпретатор находил метод init в объекте Person. Мы удачно блокировали доступ к Person‘овскому методу init, однако он нам нужен для инициализации свойств "first" и "last" . Здесь и появляется свойство класса "superclass".
 
Мы знаем, что интерпретатор обрабатывает последовательность свойства prototype объектов, пока не найдётся название, которое он ищет. Поскольку мы не хотим, чтобы интепретатор использовал метод init текущего объекта, нам нужно как-нибудь заставить его искать в свойстве prototype родительского объекта. Если мы в объекте Employee, тогда нам нужно, чтобы интерпретатор начал поиск не в Employee.prototype, а в Person.prototype-- именно для этого мы и определили свойство superclass для класса.
 
Хорошо, теперь мы знаем, где интерпретатор начнет поиск нашего "скрытого" метода init, однако как его заставить начать поиск именно там? Вот решение.

Код:
Employee.prototype = new Person();
Employee.prototype.constructor = Employee;
Employee.superclass = Person.prototype;
 
function Employee(first, last, id) {
    if ( arguments.length > 0 )
        this.init(first, last, id);
}
 
Employee.prototype.init = function(first, last, id) {    
    // вызов метода superclass
    Employee.superclass.init.call(this, first, last);
 
    //инициализация свойств
    this.id = id;
}

Каждая функция в JavaScript имеет два метода, которые позволяют вызывать метод, как будто он является методом указанного вами объекта. Это методы "call" и "apply". Мы используем "call" в данном примере.
 
Первый параметр "call" это объект, используемый в вызываемом методе. Все параметры после объекта будут использоваться как параметры вызываемого метода. "Apply" работает точно так же, однако второй параметр-- это массив данных, который будет передан методу как если бы они перечислялись по-отдельности. Это полезно, если необходимо передать все аргументы, использованные в текущем методе в метод, вызываемый посредством "apply".
Рекомендую создавать метод init для каждого создаваемого вами объекта JavaScript. Никогда не известно, будете ли вы создавать подкласс для объекта, а заранее создав для него метод init, вы подготовите его к созданию подклассов способами, описанными в данной статье.
 
Конечный код. Я использовал тот же механизм вызова метода надкласса в методах toString, поэтому в данном коде больше примеров используемой мной техники.

Код:
/*****
*
*    конструктор Person
*
*****/
function Person(first, last) {
    if ( arguments.length > 0 )
        this.init(first, last);
}
 
/*****
*
*    инициализация Person
*
*****/
Person.prototype.init = function(first, last) {
    this.first = first;
    this.last  = last;
};
 
/*****
*
*    Person toString
*
*****/
Person.prototype.toString = function() {
    return this.first + "," + this.last;
};
 
 
/*****
*
*    установление наследования для Employee
*
*****/
Employee.prototype = new Person();
Employee.prototype.constructor = Employee;
Employee.superclass = Person.prototype;
 
/*****
*
*    конструктор Employee
*
*****/
function Employee(first, last, id) {
    if ( arguments.length > 0 )
        this.init(first, last, id);
}
 
/*****
*
*    инициализация Employee
*
*****/
Employee.prototype.init = function(first, last, id) {    
    // вызов метода superclass
    Employee.superclass.init.call(this, first, last);
 
    // инициализация свойств
    this.id = id;
}
 
/*****
*
*    Employee toString
*
*****/
Employee.prototype.toString = function() {
    var name = Employee.superclass.toString.call(this);
 
    return this.id + ":" + name;
};
 
 
/*****
*
*    установление наследования для Manager
*
*****/
Manager.prototype = new Employee;
Manager.prototype.constructor = Manager;
Manager.superclass = Employee.prototype;
 
/*****
*
*    конструктор Manager  
*
*****/
function Manager(first, last, id, department) {
    if ( arguments.length > 0 )
        this.init(first, last, id, department);
}
 
/*****
*
*   инициализация Manager
*
*****/
Manager.prototype.init = function(first, last, id, department){
    // вызов метода superclass
    Manager.superclass.init.call(this, first, last, id);
 
    // инициализация свойств
    this.department = department;
}
 
/*****
*
*    Manager toString
*
*****/
Manager.prototype.toString = function() {
    var employee = Manager.superclass.toString.call(this);
 
    return employee + " manages " + this.department;
}

 
Добавлено
8AleX8

Цитата:
JavaScript Object Inheritance (наследование в JavaScript)  
  »  Статья на англ. яз. Очень интересно! Свежий взгляд.

Подправь описание темы


----------
away.

Всего записей: 4161 | Зарегистр. 25-06-2002 | Отправлено: 08:25 14-02-2003 | Исправлено: Svarga, 03:56 31-07-2004
8AleX8



Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Svarga
Молодец!!!  
 
Добавлено

Цитата:
Подправь описание темы  

Подправил.
 
Будит время.... Внимательно прочту перевод.

Всего записей: 1813 | Зарегистр. 11-12-2001 | Отправлено: 08:57 14-02-2003
myo



Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
Спасибо за информацию всем, кто принимал участие в процессе.
Очень поучительно было

Всего записей: 270 | Зарегистр. 09-09-2002 | Отправлено: 10:33 14-02-2003
8AleX8



Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
А вот ещё более не ординарный и глубокий взгляд на JavaScript.
Но к сожалению опять на английском.
JavaScript The World's Most Misunderstood Programming Language
JavaScript самый не правильно понятый в мире язык програмирования.
http://www.crockford.com/#javascript

Всего записей: 1813 | Зарегистр. 11-12-2001 | Отправлено: 23:46 28-03-2003
Svarga

Moderator
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Прямая ссылка: http://www.crockford.com/javascript/javascript.html
Касательно глубины спорить не буду
Обычные общие сведения (хотя, прочитал и имею в виду только статью с названием "JavaScript The World's Most Misunderstood Programming Language"-- в остальные статьи цикла не заглядывал, так что может я и не прав).  
 
Попытаюсь перевести сие на досуге на всеобщее обозрение.
(8AleX8, спасибо за ссылку!)


----------
away.

Всего записей: 4161 | Зарегистр. 25-06-2002 | Отправлено: 00:52 29-03-2003
LamerOK1024



Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
А можно ли в JavaScript наследовать такие методы как onclick? вобщем есть много кнопок по нажатию на которые происходит одно и тоже действие и не хочется писать обработчик для каждой кнопки, хотелось бы чтобы действия производились внутри объекта при наступлении события.

Всего записей: 37 | Зарегистр. 22-05-2008 | Отправлено: 14:55 14-01-2009
Cheery



.:МордератоР:.
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
LamerOK1024

Цитата:
вобщем есть много кнопок по нажатию на которые происходит одно и тоже действие и не хочется писать обработчик для каждой кнопки

эм.. вызвать одну и ту же функцию?


----------
Away/DND

Всего записей: 52737 | Зарегистр. 04-04-2002 | Отправлено: 19:19 14-01-2009
LamerOK1024



Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору

Цитата:
вызвать одну и ту же функцию

 
ну они и так вызывают одну и туже функцию про сто я хочу привязать это действие к событию внутри объекта ну что-то наподобие этого:
 
var obj = new Object();
 
obj.onclick = function() {
  myFunc(1);
}
 
obj.onmouseover = function() {
  myFunc(2);
}
 
document.getElementById('but1').prototype = obj;
document.getElementById('but2').prototype = obj;
...
 
т.е. я не хочу расписывать обработку события для каждой кнопки, а хочу чтобы "поведение" наследовалось от другого объекта.

Всего записей: 37 | Зарегистр. 22-05-2008 | Отправлено: 06:29 15-01-2009
Cheery



.:МордератоР:.
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
LamerOK1024
http://ajaxaspects.blogspot.com/2007/04/using-inheritance-in-javascript.html

----------
Away/DND

Всего записей: 52737 | Зарегистр. 04-04-2002 | Отправлено: 06:53 15-01-2009
LamerOK1024



Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Cheery
 
Огромно спасибо за ссылку, я много подобного находил, но там было очень сложно разобрать (просто я не понимал механизма).
Вот что у меня вышло:
 

Цитата:
 
function inheritFrom(aThis, aParent) {
    var excp;
 
    for (var property in aParent) {
        try    {
            aThis[property] = aParent[property];
        }
        catch(excp) {
        }
    }
}
 
function oParent(name) {
    this.table = name;
}
 
oParent.prototype.onmousemove = function() {
    linkBPE(this, 1);
}
oParent.prototype.onmouseout = function() {
    linkBPE(this, 0);
}
oParent.prototype.onmousedown = function() {
    getTable(this.table);
}
 
inheritFrom(document.getElementById("nSotrud"), new oParent('sotrud'));
inheritFrom(...);
...
 

 
И все! Все обработчики событий умещаются в одну строчку!

Всего записей: 37 | Зарегистр. 22-05-2008 | Отправлено: 12:37 15-01-2009
Открыть новую тему     Написать ответ в эту тему

Компьютерный форум Ru.Board » Интернет » Web-программирование » Закладки » Наследование объектов в JavaScript.


Реклама на форуме Ru.Board.

Powered by Ikonboard "v2.1.7b" © 2000 Ikonboard.com
Modified by Ru.B0ard
© Ru.B0ard 2000-2024

BitCoin: 1NGG1chHtUvrtEqjeerQCKDMUi6S6CG4iC

Рейтинг.ru