I’ve been playing with classes and subclasses in Javascript, and I thought I’d try what seems to be a simple example: a Circle
class which is initialized with cx
, cy
, (coordinates of the origin) and r
(the size of the radius). I also pass in a reference to an SVG. Then the Circle draws itself upon instantiation, like this:
let c = new Circle(svg, 100, 100, 10);
So far so good, this class definition works:
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);
}
}
Now for subclassing. I figured a good place for a .random(n)
method would be on the RandomCircle
class, so I tried this:
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)
}
}
Looks pretty good, doesn’t work, apparently because you can’t refer to this
before calling super
. So my quandary is, what do I do if I want to use class methods to calculate parameters to pass to super()
in a derived class?
<!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>