• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Dziedziczenie w Javascript. dlaczego nie mogę użyć dziedziczonej właściwości

Object Storage Arubacloud
0 głosów
173 wizyt
pytanie zadane 1 sierpnia 2019 w JavaScript przez Mariusz Podgórski Początkujący (400 p.)

Pracuje nad grą w canvas Pomyślałem sobie, że stworzę klasę Entity z której wszystkie inne obiekty klasy będą dziedziczyły i umieszczę w niej ctx,  żebym mógł rysować inne obiekty.

class Entity {

    constructor(color = 'blue', positionX = 200, positionY = 200, width = 100, height = 50) {
        this.width = width;
        this.height = height;
        this.color = color;
        this.positionX = positionX;
        this.positionY = positionY;

        this.myCanvas = document.createElement('canvas');
        this.ctx = this.myCanvas.getContext('2d');
        document.body.appendChild(this.myCanvas);
    }

}

Z powyższej klasy dziedziczy wszystkie właściwości klasa Asteroids i faktycznie w konsoli występuje widzę właściwość ctx do rysowania na canvas 

class Asteroid extends Entity {
    constructor(color, positionX, positionY, width, height) {
        super(color, positionX, positionY, width, height)
    }

    asteroidDraw = () => {

        this.ctx.fillStyle = "red";
        this.ctx.fillRect(this.positionX - 2, this.positionY - 2, 4, 4);

    }

Poniżej zamieszczam konsole z chrma jako dowód że dana klasa odziedziczyła właściwość ctx

Asteroid {canvasDraw: ƒ, rand: ƒ, myCanvas: canvas, ctx: CanvasRenderingContext2D, myCanvasWidth: 1600, …}
asteroidDraw: () => {…}
canvasDraw: () => {…}
color: "blue"
ctx: CanvasRenderingContext2D {canvas: canvas, globalAlpha: 1, globalCompositeOperation: "source-over", filter: "none", imageSmoothingEnabled: true, …}
height: 50
myCanvas: canvas
myCanvasHeight: 420
myCanvasWidth: 1600
positionX: 200
positionY: 200
rand: (minS = 0, maxS = 240) => {…}
width: 100
__proto__: Entity

Pytanie brzmi dlaczego nie mogę jej użyć w metodzie asteroidDraw = () => { Nie mogę narysować tego kwadratu. Jeżeli jednak przekaże ctx w konstruktorze wszystko jest ok kwadrat się rysuję. Dziedziczenie ctx miało mi zapewnić że będę mógł narysować każdy obiekt i nie będę musiał pamiętać o przekazywaniu ctx za każdym razem w każdym obiekcie. Na marginesie chciałbym wiedzieć dlaczego skoro właściwość jest odziedziczona nie mogę jej użyć? Z góry dziękuje za wszystkie odpowiedzi (konstruktywne odpowiedzi).

komentarz 1 sierpnia 2019 przez ScriptyChris Mędrzec (190,190 p.)

Sprawdź, czym jest this wewnątrz metody asteroidDraw.

komentarz 1 sierpnia 2019 przez Mariusz Podgórski Początkujący (400 p.)
Jest asteroidą i ?

2 odpowiedzi

+1 głos
odpowiedź 2 sierpnia 2019 przez Comandeer Guru (601,450 p.)

Ta zmienna nie jest dziedziczona. Żeby była dziedziczona, musiałaby być statycznym getterem w klasie Entity, zwracającym istniejący element canvas:

class Entity {
	static get ctx() {
		const canvas = document.querySelector( '#myCanvas' );

		return canvas.getContext( '2d' );
	}
}

Obecnie każda Twoja asteroida posiada swój własny canvas, który jest tworzony w chwili tworzenia samego obiektu (bo przy tworzeniu klasy potomnej jest wywoływany konstruktor klasy nadrzędnej; nie trzeba tego robić ręcznie, jak w Twoim kodzie) i nic nie jest dziedziczone.

Niemniej zamiast takiego rozwiązania proponowałbym zapoznać się z konceptem Dependency Injection i po prostu przekazać odpowiedni kontekst jako jeden z parametrów konstruktora. Będzie to wygodniejsze niż takie kombinowanie, a i będziesz miał większą pewność, że operujesz na prawidłowym płótnie.

Co do problemu z niewidocznością this.ctx w asteroidDraw: nie stworzyłeś tego jako metody klasy Asteroid, ale tak po prawdzie jako własność klasy, której przypisałeś funkcję strzałkową jako wartość. Twój kod jest praktycznie tożsamy z:

class Asteroid extends Entity {
	constructor(color, positionX, positionY, width, height) {
		super(color, positionX, positionY, width, height)

		this.asteroidDraw = () => {
 
			this.ctx.fillStyle = "red";
			this.ctx.fillRect(this.positionX - 2, this.positionY - 2, 4, 4);
	 
		};
	}
}

O wiele lepiej byłoby to stworzyć jako faktyczną metodę tej klasy. Wówczas wszystkie asteroidy korzystałyby z tej samej kopii tej funkcji (umieszczonej w prototypie), zamiast posiadać własną jej kopię. Niemniej oprócz tego działa to jak najbardziej poprawnie i funkcja odpala się na canvasie, jaki został stworzony w konstruktorze.

0 głosów
odpowiedź 1 sierpnia 2019 przez adrian17 Ekspert (344,860 p.)

Dziedziczenie ctx miało mi zapewnić że będę mógł narysować każdy obiekt i nie będę musiał pamiętać o przekazywaniu ctx za każdym razem w każdym obiekcie

Chwila, moment.

        this.myCanvas = document.createElement('canvas');
        this.ctx = this.myCanvas.getContext('2d');
        document.body.appendChild(this.myCanvas);

Ale tutaj każdy element tworzy własny canvas.

Podobne pytania

0 głosów
1 odpowiedź 232 wizyt
0 głosów
1 odpowiedź 89 wizyt
pytanie zadane 30 stycznia 2017 w C i C++ przez robRoy Użytkownik (970 p.)
+1 głos
0 odpowiedzi 73 wizyt
pytanie zadane 1 grudnia 2018 w JavaScript przez ptaku19 Użytkownik (800 p.)

92,575 zapytań

141,424 odpowiedzi

319,649 komentarzy

61,960 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...