2013-04-28 2 views
6

Как из OOPS базы, я всегда использую наследование как мощный инструмент для повторного использования кода,Почему Javascript не поддерживает наследование по умолчанию?

Например, если я пишу шахматную программу в OOPS и когда я реализую is-a отношения, как,

Class Piece{ 
    int teamColor; 
    bool isLive; 
    Positon pos; 
    int Points; 
    ....... 
    int getTeamColor(){....} 
    ....... 
}; 

Class Rook extend Piece{ //`is-a` 
...... // No getTeamColor() definition here.. because the parent has the definition. 
}; 

Class Pawn extend Piece{ //`is-a` 
......// No getTeamColor() definition here.. because the parent has the definition. 
}; 

I мог бы сделать это с отношением has-a в javascript, но недостаток, который я вижу, - это Я должен переопределить каждую функцию в производном классе.

Пример: переопределение getTeamColor() снова в каждом ладья, конь, пешки, король .... и т.д ..

 var Pawn = function(teamColor,pos){ 
    var piece = new Piece(teamColor,pos); 
    ....... 

    this.getTeamColor = function(){   
      return piece.getTeamColor(); 
    }; 
    } 

Мой вопрос, Почему Javascript оленья кожа поддерживает классическое наследование в качестве опции по умолчанию ?

+0

Посмотрите на jOOPL (http://joopl.codeplex.com). Это объектно-ориентированная библиотека на 100% JavaScript, которая расширяет язык поддержки ООП класса. Таким образом, он имеет наследование и полиморфизм (и многие другие функции). Я собираюсь выпустить новую версию за несколько дней с большим количеством улучшений. –

+6

JavaScript поддерживает наследование * если вы его используете *. Посмотрите «Цепочка прототипов JavaScript». Что касается «Почему javascript не поддерживает классическое наследование как вариант по умолчанию?» - потому что именно так был определен JavaScript. Почему у Java нет черт, кроме Scala? Почему Python поддерживает MI, хотя Ruby этого не делает? Почему C++ не имеет множественной отправки от Dylan? Почему Эйфель разрешает перерыв LSP? Ну, они * разные языки * и утверждать, что один из них правильный - через косвенные средства «классического» - это отрицать, что другой подход является (или более) действительным. – user2246674

+0

Полная статья от Mozilla Developer Network о деталях объектной модели javascript. [LINK HERE] (https://developer.mozilla.org/en-US/docs/JavaScript/Guide/Details_of_the_Object_Model). Эта статья охватывает наследование, иерархию и отношения при сравнении между Java (на основе класса) и Javascript (на основе Prototype). –

ответ

13

JavaScript делает наследование поддержки на прототипном пути. Здесь вам нужны не классы, а инкапсуляция поведения и возможность переопределения.

function Piece() { } 

Piece.prototype.color = "white"; 
Piece.prototype.getColor = function() { return this.color } 
Piece.prototype.move = function() { throw "pure function" }; 

function Pawn() { } 
Pawn.prototype = new Piece();  
Pawn.prototype.move = function() { alert("moved"); } 

и теперь:

var p = new Pawn(); p.color = "black"; 

> p instanceof Piece 

правда

p instanceof Pawn 

правда

p.getColor() 

"черный"

p.move() 

начеку ...

Это основной подход, и есть много библиотек там, которые превращают это в чем-то знакомое для ребят, желающих классы - так сказать.

Например, с JayData вы можете написать предыдущие более герметизированным способ (с бонусом автоматического вызова конструктора вверх по цепочке:

var Piece = $data.Base.extend("Piece", { 
    move: function() { throw "pure class" } 
}); 

var Pawn = Piece.extend("Pawn", { 
    move: function() { ... } 
}); 

var p = new Pawn(); 
7

Потому что Javascript не является class-based object-oriented language, а скорее prototypal. Это просто дизайнерское решение.

Кроме того, Javascript никогда не был «предназначен» для всех вещей, которые мы делаем с ним сегодня (от Node.js до ASM.js). Тот факт, что он по-прежнему имеет значение, является завещанием Брендан Эйх и Ко. Поэтому вы можете задаться вопросом, почему X или Y никогда не были реализованы в JS, но факт в том, что мы используем JS для вещей, которые 20 лет назад были бы непредсказуемыми.

1

Многие хорошие книги на различных традиционных языках OO (включая Java, C# и C++), в частности, советуют не использовать «наследование реализации», где это возможно. Пример: Эффективная Java от Джошуа Блоха.

Странный факт заключается в том, что хотя наследование реализации, похоже, придает правильную «форму» вашему коду, это не помогает решить проблему; чаще это вызывает проблемы в долгосрочной перспективе.

Эти авторы, как правило, дают свое благословение вместо «наследования интерфейсов», но на языке утиного типа, таком как JavaScript, нет необходимости явно объявлять такое наследование.

И в JS вы можете «повторно использовать» одну и ту же функцию, просто назначив ее как свойство для нескольких объектов. Какой бы вкус наследования вам ни понадобился, вы можете вызывать это из ничего.

1

В JavaScript нет даже классов класса ООП, вы просто можете имитировать нечто подобное.

В вашем примере, вы можете получить наследство, делая

var Pawn = function(teamColor, pos) { 
    Piece.call(this, teamColor, pos); 
} 

Однако, как правило, должны приложить методы к функции прототипа, а не к любому новому созданному объекту. В этом случае, вы можете моделировать наследование пути создания цепи прототипов, например, как это делает CoffeeScript:

var a, b, _ref, 
    __hasProp = {}.hasOwnProperty, 
    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; 

a = (function() { 
    function a() {} 

    return a; 

})(); 

b = (function(_super) { 
    __extends(b, _super); 

    function b() { 
    _ref = b.__super__.constructor.apply(this, arguments); 
    return _ref; 
    } 

    return b; 

})(a); 
+4

- это чрезмерность imho (и немного тарабарщина) для требуемых задач: переопределение поведения по дереву классов. –

0

Следующий блок кода будет «расширить» один прототип JavaScript из другой, и убедитесь, что оператор «InstanceOf» работает правильно для базовых и производных классов.

из того, что я могу сказать, установив прототип TestB на новую Testa позволяет логической consistancy оператора «InstanceOf».

Передача этого TestA дает новый экземпляр всем желаемым свойствам и методам.

Выполнение этого способа - это своего рода баланс между стилистическими желаниями и прагматическими. Это будет работать в большинстве браузеров, даже Internet Explorer, если вы будете вынуждены его поддерживать. Это также помогает, поскольку методы, содержащиеся в одном блоке, «чувствуют» много, как ваш традиционный синтаксис OO.

Кроме того, основная причина, по которой JavaScript не поддерживает традиционный стиль OO, объясняется его основополагающей философией. Основополагающая философия - это свобода. Эта свобода предназначена для того, чтобы позволить разработчикам создавать собственные стили в соответствии с потребностями проекта.

Смежные вопросы