我正在尝试创建image library on github called Jimp的子类。据我所知,你不会以通常的方式实例化这个类。似乎该类有一个名为new Jimp()
的静态方法,而不是说read
,它充当构造函数。来自文档...
Jimp.read("./path/to/image.jpg").then(function (image) {
// do stuff with the image
}).catch(function (err) {
// handle an exception
});
从文档中可以看出,image
返回的read()
是允许调用者执行image.resize( w, h[, mode] );
等内容的实例。
我想允许我的子类调用者以一个不同的静态方法开始,该方法读取一个图像并做一堆东西,总结如下......
class MyJimpSubclass extends Jimp {
static makeAnImageAndDoSomeStuff(params) {
let image = null;
// read in a blank image and change it
return Jimp.read("./lib/base.png").then(_image => {
console.log(`image is ${_image}`);
image = _image;
let foo = image.bar(); // PROBLEM!
// ...
// ...
.then(() => image);
}
bar() {
// an instance method I wish to add to the subclass
}
// caller
MyJimpSubclass.makeAnImageAndDoSomeStuff(params).then(image => {
//...
});
您可能会猜到nodejs在let foo = image.bar();
行上生气,说
TypeError image.bar不是函数
我认为这是可以理解的,因为我使用Jimp.read()
获得了该图像。当然,这不会返回我的子类的实例。
MyJimpSubclass.read()
。同样的问题。第二个想法:实现我自己的静态读取方法。同样的问题。
static read(params) {
return super.read(params);
}
第三个想法:问SO
答案 0 :(得分:1)
implementation of Jimp.read
具体指Jimp
,所以你必须在你的子类中复制和更改它(ick,但不会破坏任何东西,因为构造函数也是API的一部分)或者发出pull请求将其更改为this并明确支持子类:
static read(src) {
return new Promise((resolve, reject) => {
void new this(src, (err, image) => {
if (err) reject(err);
else resolve(image);
});
});
}
或者,您可以将所有功能实现为模块上的一组功能。在发出拉取请求后,这将是我的列表中的下一个。不推荐代理。
const makeAnImageAndDoSomeStuff = (params) =>
Jimp.read("./lib/base.png").then(image => {
console.log(`image is ${image}`);
let foo = bar(image);
// …
return image;
});
function bar(image) {
// …
}
module.exports = {
makeAnImageAndDoSomeStuff,
bar,
};
即使更改原型也会比代理更好(但这只是第一个选项的更糟糕的版本,重新实现read
):
static read(src) {
return super.read(src)
.then(image => {
Object.setPrototypeOf(image, this.prototype);
return image;
});
}
答案 1 :(得分:1)
你有几个选择。最干净的可能是创建一个像你一样的子类,但是然后在它上面实现Jimp
静态方法,以及你自己的方法。在这种情况下,它不是真正的继承,所以不要使用extends
。
class MyJimp {
static read(...args) {
return Jimp.read.apply(Jimp, args);
}
static makeAnImage(params) {
return this.read(params)
.then(image => {
// do stuff
return image
});
}
}
从那里开始,我会创建一个包含所有要应用于image
的新函数的对象:
const JimpImageExtension = {
bar: () => { /* do something */ }
};
最后,在静态方法中,获取图片并使用Object.assign()
将新功能应用于其中:
class MyJimp {
static read(...args) {
return Jimp.read.apply(Jimp, args)
.then(image => Object.assign(image, JimpImageExtension));
}
static makeAnImage(params) {
return this.read(params)
.then(image => {
// do stuff
image.bar();
return image;
});
}
}
这应该通过将额外的功能应用于图像来实现。您只需要确保在每个可以生成图像的点上应用它(如果不仅仅是read
)。因为在其他函数中,它使用的是read()
版本,所以只需要在一个函数中添加函数。
另一种方法是如果Jimp
使他们的图像类可访问,你也可以将它们添加到它的原型中(虽然通常在像这样的库中,该类经常是不可访问的或根本不是一个类)
答案 2 :(得分:1)
这可能是一种方法。从您自己的<div class="form-group">
<select class="selectpicker search-fields" id="ct" name="ct" data-live-search="true" data-live-search-placeholder="Search value" style='z-index:999 !important'>
<option value="">Contract Types</option>
@foreach (\App\ContractType::all() as $ct)
<option value="{{ $ct->id }}">{{ $ct->type }}</option>
@endforeach
</select>
</div>
方法开始,让它更改返回对象的原型。
read