Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Как правильно реализовать наследование? (https://javascript.ru/forum/misc/46446-kak-pravilno-realizovat-nasledovanie.html)

Universe 10.04.2014 12:16

Как правильно реализовать наследование?
 
Добрый день. Разбираюсь с наследованием и хотел спросить, как правильно его реализовать.
Например есть такой вариант:
(function ()
{
	function Rect(width, height)
	{
		this.width = width;
		this.height = height;
	}

	window.Rect = Rect;
}());

(function ()
{
	function Box(x,y, width, height)
	{
		Rect.call(this, width, height);
		this.x = x;
		this.y = y;
	}

	Box.prototype = Object.create(Rect);

	window.Box = Box;
}());

var box = new Box(5,5,100,100);
var box2 = new Box(5,5,200,200);

Он вполне рабочий, но есть несколько моментов которые я не до конца понимаю. Например, я хочу сделать переменную, которая будет едина для обоих box'ов. Логика подсказывает что её нужно прописывать на прототип при объявлении, например вот так:
Box.prototype.someVar = 25;


Но если я меняю такую переменную на уровне бокса, например:
box.someVar = 30;

то она и меняется только у этого бокса.

Следоавтельно вопрос: правильно ли организовано наследование в примере выше и если да, то как мне создать "общую" переменную в такой реализации?

Universe 10.04.2014 12:22

Посмотрел структуру объектов в консоли. Получается что в моей реализации создаётся "промежуточный" объект.


Почему прототипом моего объекта box становится Function, а не Rect?

Aetae 10.04.2014 12:26

Если утрировать, то как-то так:
(function ()
{
    var privateVar;
    function Box(x,y, width, height)
    {
        Rect.call(this, width, height);
        this.x = x;
        this.y = y;
    }
 
    Box.prototype = Object.create(Rect);
    Box.prototype.setVar = function(val){privateVar = val};
    Box.prototype.getVar = function(){return privateVar};
    window.Box = Box;
}());
 
var box = new Box(5,5,100,100);
var box2 = new Box(5,5,200,200);


Цитата:

Сообщение от Universe (Сообщение 307074)
Почему прототипом моего объекта box становится Function, а не Rect?

Потому что Rect - function, а function - instanceof object. Что вы вообще хотели получить?

nerv_ 10.04.2014 13:09

вместо
Цитата:

Сообщение от Universe
Box.prototype.someVar = 25;

надо
Rect.prototype.someVar = 25;

т.к. Box наследует от Rect

Можешь это почитать

Цитата:

Сообщение от Universe
Следоавтельно вопрос: правильно ли организовано наследование в примере выше и если да, то как мне создать "общую" переменную в такой реализации?

я ответил про общую для Rect & Box

function Rect() {}
Rect.prototype.x = 1;

function Box() {}
Box.prototype = Object.create(Rect.prototype);

var box = new Box();
alert(box.x);

Universe 10.04.2014 13:11

Я просто к чему спрашиваю, может правильнее было бы присваивать прототипу Box прототип Rect?
Вот так:
Box.prototype = Object.create(Rect).prototype;


Не вижу смысла в этой доп. прослойке.

Sweet 10.04.2014 13:26

Цитата:

Сообщение от Universe
Логика подсказывает что её нужно прописывать на прототип при объявлении, например вот так:
Box.prototype.someVar = 25;

Но если я меняю такую переменную на уровне бокса, например:
box.someVar = 30;

Лично мне логика подсказывает, что менять "переменную" (свойством называется) нужно там, куда её и "прописывал".:) Т.е. меняй свойство в прототипе:
Box.prototype.someVar = 30;

Universe 10.04.2014 13:47

Цитата:

Т.е. меняй свойство в прототипе:
Box.prototype.someVar = 30;
Мне сейчас интересен именно вариант изменения через свойство переменной. Смысл мне тогда от наследования, если придётся всегда явно обращаться к его прототипу.
Цитата:

надо
Rect.prototype.someVar = 25;
т.к. Box наследует от Rect
Структурно может быть и так, но в результате тот же эффект

хотя с объектами такого не происходит. Я понимаю что из ситуации можно выйти путём создания геттера и сеттера для изминения примитивного значения
Box.prototype.someVar= 30;
	Box.prototype.getVal = function (){
		return this.someVar;
	}
	Box.prototype.setVal = function(val){
		Box.prototype.someVar= val;
	}

Но мне важно понять, почему именно примитивные значения не являются общими ссылками?

Sweet 10.04.2014 14:09

Цитата:

Сообщение от Universe
Смысл мне тогда от наследования, если придётся всегда явно обращаться к его прототипу

Смысл наследования не в том, чтобы неявно обращаться к прототипу. Вообще, нужное тебе поведение в ООП реализуется через статические члены класса:
Box.someVar= 30; // вместо Box.prototype.someVar= 30

Octane 10.04.2014 14:53

Цитата:

Сообщение от Universe
Я просто к чему спрашиваю, может правильнее было бы присваивать прототипу Box прототип Rect?
Вот так:
Box.prototype = Object.create(Rect).prototype;

Box.prototype = Object.create(Rect.prototype);



Цитата:

Сообщение от Universe
с объектами такого не происходит

Цитата:

Сообщение от Universe
почему именно примитивные значения не являются общими ссылками?

С ссылками на объекты все точно так же:
function A() {}
A.prototype.x = {};

function B() {}
B.prototype = Object.create(A.prototype);

var b = new B;
b.x = {};

alert(A.prototype.x === b.x); //→ false

Так уж сделано, что явное присваивание создает собственное свойство.

Universe 10.04.2014 16:05

Большое спасибо за помощь!:)


Часовой пояс GMT +3, время: 21:05.