我正在学习如何用JavaScript制作面向对象编程。是否有接口概念(如Java的接口)?
这样我就可以创建一个监听器。
我正在学习如何用JavaScript制作面向对象编程。是否有接口概念(如Java的接口)?
这样我就可以创建一个监听器。
当前回答
像这样的抽象接口
const MyInterface = {
serialize: () => {throw "must implement serialize for MyInterface types"},
print: () => console.log(this.serialize())
}
创建一个实例:
function MyType() {
this.serialize = () => "serialized "
}
MyType.prototype = MyInterface
并使用它
let x = new MyType()
x.print()
其他回答
希望任何还在寻找答案的人都能从中找到帮助。
你可以尝试使用代理(这是自ECMAScript 2015以来的标准):https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy
latLngLiteral = new Proxy({},{
set: function(obj, prop, val) {
//only these two properties can be set
if(['lng','lat'].indexOf(prop) == -1) {
throw new ReferenceError('Key must be "lat" or "lng"!');
}
//the dec format only accepts numbers
if(typeof val !== 'number') {
throw new TypeError('Value must be numeric');
}
//latitude is in range between 0 and 90
if(prop == 'lat' && !(0 < val && val < 90)) {
throw new RangeError('Position is out of range!');
}
//longitude is in range between 0 and 180
else if(prop == 'lng' && !(0 < val && val < 180)) {
throw new RangeError('Position is out of range!');
}
obj[prop] = val;
return true;
}
});
然后你就可以轻松地说:
myMap = {}
myMap.position = latLngLiteral;
如果你想通过instanceof (@Kamaffeather问)检查,你可以像这样把它包装在一个对象中:
class LatLngLiteral {
constructor(props)
{
this.proxy = new Proxy(this, {
set: function(obj, prop, val) {
//only these two properties can be set
if(['lng','lat'].indexOf(prop) == -1) {
throw new ReferenceError('Key must be "lat" or "lng"!');
}
//the dec format only accepts numbers
if(typeof val !== 'number') {
throw new TypeError('Value must be numeric');
}
//latitude is in range between 0 and 90
if(prop == 'lat' && !(0 < val && val < 90)) {
throw new RangeError('Position is out of range!');
}
//longitude is in range between 0 and 180
else if(prop == 'lng' && !(0 < val && val < 180)) {
throw new RangeError('Position is out of range!');
}
obj[prop] = val;
return true;
}
})
return this.proxy
}
}
这可以在不使用Proxy的情况下完成,而是使用类getter和setter:
class LatLngLiteral {
#latitude;
#longitude;
get lat()
{
return this.#latitude;
}
get lng()
{
return this.#longitude;
}
set lat(val)
{
//the dec format only accepts numbers
if(typeof val !== 'number') {
throw new TypeError('Value must be numeric');
}
//latitude is in range between 0 and 90
if(!(0 < val && val < 90)) {
throw new RangeError('Position is out of range!');
}
this.#latitude = val
}
set lng(val)
{
//the dec format only accepts numbers
if(typeof val !== 'number') {
throw new TypeError('Value must be numeric');
}
//longitude is in range between 0 and 180
if(!(0 < val && val < 180)) {
throw new RangeError('Position is out of range!');
}
this.#longitude = val
}
}
没有,但是它有mixins。 您可以使用抽象子类或mixins作为替代https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes#mix-ins
虽然javaScript中不像Java中那样有接口,但你可以用这条消息下的代码来模仿这种行为。因为接口基本上是一个强制契约,你可以自己构建它。
下面的代码来自3个类:接口、父类和子类。
接口中有检查方法和属性是否存在的方法。 父类用于使用Interface类在子类中强制执行所需的方法和属性。 孩子是父母规则强制执行的类别。
在您正确地设置它之后,如果子程序中缺少方法或属性,那么您将在控制台中看到一个错误,如果子程序正确地实现了契约,则什么也没有。
class Interface {
checkRequiredMethods(methodNames) {
setTimeout( () => {
const loopLength = methodNames.length;
let i = 0
for (i; i<loopLength; i++) {
if (typeof this[methodNames[i]] === "undefined") {
this.throwMissingMethod(methodNames[i]);
}
else if (typeof this[methodNames[i]] !== "function") {
this.throwNotAMethod(methodNames[i]);
}
}
}, 0);
}
checkRequiredProperties(propNames) {
setTimeout( () => {
const loopLength = propNames.length;
let i = 0
for (i; i<loopLength; i++) {
if (typeof this[propNames[i]] === "undefined") {
this.throwMissingProperty(propNames[i]);
}
else if (typeof this[propNames[i]] === "function") {
this.throwPropertyIsMethod(propNames[i]);
}
}
}, 0);
}
throwMissingMethod(methodName) {
throw new Error(`error method ${methodName} is undefined`);
}
throwNotAMethod(methodName) {
throw new Error(`error method ${methodName} is not a method`);
}
throwMissingProperty(propName) {
throw new Error(`error property ${propName} is not defined`);
}
throwPropertyIsMethod(propName) {
throw new Error(`error property ${propName} is a method`);
}
}
class Parent extends Interface {
constructor() {
super()
this.checkRequiredProperties([
"p1",
"p2",
"p3",
"p4",
"p5"
]);
this.checkRequiredMethods([
"m1",
"m2",
"m3",
"m4"
]);
}
}
class Child extends Parent {
p1 = 0;
p2 = "";
p3 = false;
p4 = [];
p5 = {};
constructor() {
super();
}
m1() {}
m2() {}
m3() {}
m4() {}
}
new Child()
我知道这是一个老问题,但我最近发现自己越来越需要一个方便的API来根据接口检查对象。所以我写了这个:https://github.com/tomhicks/methodical
它也可以通过NPM: NPM install methodical获得
它基本上完成了上面建议的所有事情,并有一些更严格的选项,而且所有这些都不需要执行大量if (typeof x.method === 'function')样板文件。
希望有人觉得它有用。
这是旧的,但我实现了在ES6上使用的接口,没有转译器。
https://github.com/jkutianski/ES6-Interfaces