2016-11-04 2 views
0

Я играл с классами и подклассами в Javascript, и я подумал, что попробую, что кажется простым примером: класс Circle, который инициализируется cx , cy, (координаты начала координат) и r (размер радиуса). Я также передаю ссылку на SVG. Тогда круг рисует себя на конкретизации, например:Использование методов для вычисления параметров конструктора в производном классе в JS

let c = new Circle(svg, 100, 100, 10); 

До сих пор так хорошо, это определение класса работает:

class Circle { 
    constructor(svg,r,cx,cy){ 
    this.svg = svg; 
    this.circle = document.createElementNS("http://www.w3.org/2000/svg", "circle"); 
    this.circle.setAttribute("cx", cx); 
    this.circle.setAttribute("cy", cy); 
    this.circle.setAttribute("r", r); 

    this.draw() 
    } 
    draw(){ 
    this.svg.appendChild(this.circle); 
    } 
} 

Теперь для подклассов. Я полагал, что хорошее место для метода .random(n) бы на RandomCircle классе, поэтому я попытался это:

class RandomCircle extends Circle { 
    constructor(svg){ 
    cx = this.random(svg.getAttribute('width')) // error 
    cy = this.random(svg.getAttribute('height')) // error 
    r = this.random(10); // error 
    super(svg,cx,cy,r); 
    this.draw(); 
    } 
    random(n){ 
    return Math.floor(Math.random()*n) 
    } 
} 

выглядит довольно хорошо, не работает, по-видимому, потому, что вы не можете обратиться к this перед вызовом super. Итак, мое затруднение: что мне делать, если я хочу использовать методы класса для вычисления параметров для перехода к super() в производном классе?

<!DOCTYPE html> 
<html lang="en"> 
<head> 
    <meta charset="UTF-8"> 
    <title>random circles</title> 
</head> 
<body> 

<svg style="border:1px solid black" width=500 height=500></svg> 

<script> 
class Circle { 
    constructor(svg,r,cx,cy){ 
    this.svg = svg; 
    this.circle = document.createElementNS("http://www.w3.org/2000/svg", "circle"); 
    this.circle.setAttribute("cx", cx); 
    this.circle.setAttribute("cy", cy); 
    this.circle.setAttribute("r", r); 

    this.draw() 
    } 
    draw(){ 
    this.svg.appendChild(this.circle); 
    } 
} 

class RandomCircle extends Circle { 
    constructor(svg){ 
    cx = this.random(svg.getAttribute('width')) // error 
    cy = this.random(svg.getAttribute('height')) // error 
    r = this.random(10); // error 
    super(svg,cx,cy,r); 
    this.draw(); 
    } 
    random(n){ 
    return Math.floor(Math.random()*n) 
    } 
} 

let svg = document.querySelector('svg'); 
Array(3).fill().forEach(() => new Circle(svg, 10,Math.floor(Math.random()*500),Math.floor(Math.random()*500))); // these are fine 
new RandomCircle(svg); // this fails 
</script> 

</body> 
</html> 
+0

Мой главный вопрос, почему это классный метод? Для этого, по крайней мере, эта функция легко может быть автономной функцией. – loganfsmyth

+0

Возможно, так, в этом случае. Но наверняка в какой-то момент полезно использовать методы класса для вычисляемых параметров конструктора для расширенных классов. – pat

+0

Методы имеют доступ к свойствам экземпляра, которые предположительно не инициализируются перед вызовом конструктора - это один аргумент против использования методов класса в этом случае. – artem

ответ

0

Используйте новые методы установки и улавливания ES2015. Также super() должен быть первым вызовом метода в методе конструктора.

class Circle { 
    constructor(cx) { 
    this.cx = cx; 
    … 
    } 

    get cx() { 
    return this.cx; 
    } 

    set cx(cx) { 
    this.cx = cx; 
    } 

} 

class RandomCircle extends Circle { 
    constructor() { 
    super(); 
    this.cx = random(10); 
    } 

    random(n) { 
    … 
    } 
} 

Здесь большое видео учебник о классах ES2015: https://www.youtube.com/watch?v=EUtZRwA7Fqc

Я также рекомендую «Принципы объектно-ориентированного JavaScript» Николаса C. Zakas https://www.amazon.com/Principles-Object-Oriented-JavaScript-Nicholas-Zakas/dp/1593275404

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