提问人:Tobias Dräger 提问时间:9/14/2023 最后编辑:Tobias Dräger 更新时间:9/19/2023 访问量:57
当不同的类使用相同的方法但具有不同的构造函数时,如何避免重复的代码?
How to avoid repetitive code when different classes use the same methods but have different constructors?
问:
我已经在代码上工作了几个月,它工作得很好,但是我添加的功能越多,我就越想以某种方式减少代码量,因为我在各种类中使用相同的函数。
该代码由一个名为“Shape”的原始类组成,此处创建了各种函数。然后这里有各种称为“矩形”和“六边形”的新类。在这些的构造函数中,类“Shape”用行“”和“”调用。否则,类“Rectangle”、“Hexagon”等使用相同的函数(例如“”),唯一的区别是数组的引用,例如“Rectangle”类中的“”和类“Hexagon”中的“”。this.rec = new Shape {...}
this.hex = new Shape {...}
plotShape
this.rec.xCoordinates
this.hex.xCoordinates
在代码的后面部分,这些类与行 “” 和 “” 一起使用。recShape = new Rectangle {...}
hexShape = new Hexagon {...}
所以我的问题是,什么是减少代码重复的好方法?
首先,一些代码片段可以更好地理解我在说什么。
下面是原始类的构造函数以及该类中包含的函数:
export class Shape {
constructor (options) {
this.size = options.size
this.type = options.type
switch (this.type) {
...
case 4:
this.gridsizex = options.gridsizex
this.gridsizey = options.gridsizey
break
case 6:
this.gridsize = options.gridsize
break
}
this.xCoordinates = new Float64Array()
this.yCoordinates = new Float64Array()
}
createShape() {
this.xCoordinates = new Float64Array(this.size * this.size)
this.yCoordinates = new Float64Array(this.size * this.size)
switch (this.type) {
...
case 4:
for (let i = 0; i < this.size; i++) {
for (let j = 0; j < this.size; j++) {
let pos = i * this.size + j
this.yCoordinates[pos] = i * this.gridsizey
this.xCoordinates[pos] = j * this.gridsizex
}
}
break
case 6:
let distXh = this.gridsize
let distYh = distXh * ...
for (let i = 0; i < this.size; i++) {
for (let j = 0; j < this.size; j++) {
let pos = i*this.size+j
this.yCoordinates[pos] = i * distYh
this.xCoordinates[pos] = (j * distXh + i * (distXh / 2))
while ((this.xCoordinates[pos] - (this.size * distXh)) >= 0) {
this.xCoordinates[pos] -= (this.size * distXh)
}
}
}
break
}
}
}
以下是从该 OG 类创建的类以及函数。在完整的代码中,每个类中都有更多的函数(使用 Shape 类中的函数和数组),但就像函数一样,它们基本上是相同的。plotShape
plotShape
class Rectangle {
constructor (options) {
this.size = options.size
this.gridsizex = options.gridsizex
this.gridsizey = options.gridsizey
this.rec = new Shape ({
size: this.size,
type: 4,
gridsizex: this.gridsizex
grdisizey: this.gridsizey
})
this.rec.createShape()
}
plotShape (plot) {
plot.data = {
xAxis: this.rec.xCoordinates,
yAxis: this.rec.yCoordinates,
}
}
}
class Hexagon {
constructor (options) {
this.size = options.size
this.gridsize = options.gridsize
this.hex = new Shape ({
size: this.size,
type: 6,
gridsize: this.gridsize
})
this.hex.createShape()
}
plotShape (plot) {
plot.data = {
xAxis: this.hex.xCoordinates,
yAxis: this.hex.yCoordinates,
}
}
}
recShape = new Retangle({
size: 6,
gridsizex: 3,
gridsizey: 2,
})
hexShape = new Hexagon ({
size: 6,
gridsize: 1,
})
function depiction(){
recShape.plotShape(shapePlot)
hexShape.plotShape(shapePlot)
}
我一直在尝试创建一个名为“Forms”的新类,在其中创建所有函数,然后将类“Rectangle”、“Hexagon”等扩展到类“Forms”。然后,这些子类可以一起使用所有这些函数,这样我就可以节省很多代码行。但是因为我在所有类中都以不同的方式称呼这个类“形状”,所以我不太确定该怎么做,因为我总是到达一个点,我意识到这是行不通的。另一种方法可能是使用静态方法,但是我仍然没有真正理解它们是如何工作的。
话虽如此,我没有代码可以展示以前的尝试,因为我总是在某一时刻意识到它不起作用。
答:
您使用的是聚合模式,而此处的普通继承是更好的选择。这就是说六边形有形状和说六边形是形状的区别。后者是继承。
与此相关,您不需要属性。这来自您创建的对象的原型,您可以测试而不是 .type
hexShape instanceof Hexagon
hexShape.type == 6
因此,构造函数只需要一个 ,因此我不会将其作为对象传递 - 除非您有适用于所有形状的其他选项,否则这似乎有点矫枉过正。Shape
size
option
您的代码似乎代表了大型代码库的点点滴滴,因此我将把相同的点滴修改为该模式:
class Shape {
constructor(size) {
this.size = size;
}
createGrid() {
this.xCoordinates = new Float64Array(this.size * this.size);
this.yCoordinates = new Float64Array(this.size * this.size);
}
plotGrid(plot) {
plot.data = {
xAxis: this.xCoordinates,
yAxis: this.yCoordinates,
}
//...
}
}
class Rectangle extends Shape {
constructor (options) {
super(options.size);
this.gridsizex = options.gridsizex;
this.gridsizey = options.gridsizey;
this.createGrid();
}
createGrid() {
super.createGrid();
for (let i = 0; i < this.size; i++) {
for (let j = 0; j < this.size; j++) {
let pos = i * this.size + j
this.yCoordinates[pos] = i * this.gridsizey
this.xCoordinates[pos] = j * this.gridsizex
}
}
}
}
class Hexagon extends Shape {
constructor(options) {
super(options.size);
this.gridsize = options.gridsize;
this.createGrid();
}
createGrid() {
super.createGrid();
let distXh = this.gridsize;
let distYh = distXh /* ... */
for (let i = 0; i < this.size; i++) {
for (let j = 0; j < this.size; j++) {
let pos = i*this.size+j;
this.yCoordinates[pos] = i * distYh;
this.xCoordinates[pos] = (j * distXh + i * (distXh / 2));
while ((this.xCoordinates[pos] - (this.size * distXh)) >= 0) {
this.xCoordinates[pos] -= (this.size * distXh);
}
}
}
}
}
const recShape = new Rectangle({
size: 6,
gridsizex: 3,
gridsizey: 2,
});
const hexShape = new Hexagon({
size: 6,
gridsize: 1,
});
function depiction(shapePlot) {
recShape.plotGrid(shapePlot);
hexShape.plotGrid(shapePlot);
}
评论