JavaScript事件系统是否违反了LSP?

栏目: JavaScript · 发布时间: 5年前

内容简介:http://stackoverflow.com/questions/43244192/does-the-javascript-event-system-violates-the-lsp
我更多的是要求这个好奇,而不是真正关心它,但是我一直在想,JavaScript事件系统是否违反了 Liskov substitution principle (LSP)

.

通过致电 EventTarget.dispatchEvent ,我们可能会派出一个任意类型的 Event ,可能会被注册的 EventListener 处理.

interface EventListener {
  void handleEvent(in Event evt);
}

如果我正确地理解LSP,那意味着anyEventListener.handleEvent(anyEvent)不应该失败.然而,通常情况并非如此,因为事件侦听器将经常使用专门的事件子类型的属性.

在不支持泛型的类型语言中,该设计基本上需要将Event对象缩减为EventListener中的预期子类型.

从我的理解来看,上述设计可以被认为是违反LSP的.我是正确的还是通过 EventTarget.addEventListener 注册侦听器时必须提供类型的简单事实可以防止LSP违规?

编辑:

虽然每个人似乎都专注于事件子类没有违反LSP,但实际上我担心的事实是,EventListener实现者将通过限制EventListener接口的前提条件来违反LSP. void handleEvent(在事件evt)中的任何事情都没有告诉你通过传递错误的事件子类型可能会中断某些事情.

在具有泛型的强类型语言中,界面可以表示为EventListener<T extends Event>使得实施者可以明确地使合同明确. SomeHandler实现了EventListener<SomeEvent>.

在JS中,显然没有实际的接口,但是事件处理程序仍然需要符合规范,并且该规范中没有任何允许处理程序来判断它是否可以处理特定类型的事件.

这不是一个真正的问题,因为预期不会自己调用监听器,而是被注册并与特定类型相关联的EventTarget调用.

我只是根据理论是否违反LSP感兴趣.我想知道如果要避免这种违规行为(如果这样被认为是合理的话),那么合同就需要像以下那样(尽管实用主义可能做得更好)

interface EventListener {
  bool handleEvent(in Event evt); //returns wheter or not the event could be handled
}

LSP的含义非常简单:Subtype不能以违反其超类型行为的方式进行操作.那个“超类型”行为是基于设计定义的,但一般来说,它只是意味着可以继续使用该对象,就像它是项目中任何位置的超类型一样.

所以,在你的情况下,它应该遵循以下几点:

(1)KeyboardEvent可以用于预期事件代码的任何地方;

(2)对于Event中的任何函数Event.func(),相应的KeyboardEvent.func()接受Event.func()的参数或其超类型的类型,返回Event.Func()或其子类型的类型,并抛出Event.func()throws或其子类型;

(3)通过对Event.func()(历史规则)不能发生的方式,KeyboardEvent.func()的调用不会改变KeyboardEvent的事件部分(数据成员).

什么是LSP不需要的,对于func()的KeyboardEvent实现有任何限制,只要它在概念上是什么Event.func()应该的.因此,它可以使用Event不被使用的函数和对象,包括在您的情况下,其自身对象的事件不被事件超类型识别.

编辑问题:

替代原则要求子类型(概念上)与其超类型在超类型预期的任何地方相同.

因此,您的问题归结为“如果功能签名需要事件,这不是预期的吗?”

这个答案可能会让你感到惊讶,但它是 – “不,不是”.

其原因是该函数的隐式接口(或隐式契约,如果您愿意).正如你正确地指出的那样,有一些语言具有非常强大和复杂的打字规则,允许更好地定义显式接口,从而缩小允许使用的实际类型.然而,正式的论证类型并不总是预期的合约.

在没有强(或任何)打字的语言中,函数的签名对于期望的参数类型没有任何意义或一点点.然而,他们仍然希望将论点限于一些隐含的合同.例如,这是 python 函数做什么,C模板函数做什么,C做什么函数得到void *.事实上,他们没有句法机制来表达这些要求,并没有改变他们期望参数服从已知合同的事实.

即使非常强的类型的语言,如 Java 或C#,也不能总是使用其声明的类型定义参数的所有要求.因此,例如,您可以使用相同的类型调用乘法(a,b)和除(a,b) – 整数,双精度,无论如何;但是,devide()期望一个不同的合同:b不能为0!

当您现在看事件机制时,您可以理解,并不是每个监听器都被设计为处理任何事件.使用一般的事件和侦听器参数是由于语言限制(所以在Java中,你可以更好地定义正式的合同,在Python中,而不是在JS中).你应该问的是:

代码中有没有一个地方可以使用事件类型的对象(不是事件的其他特定子类型,但是事件本身),但是KeyboardEvent可能不是?另一方面 – 代码中是否有一个可以使用Listener对象(而不是某个特定子类型)的地方,但该特定的监听器可能不是?如果两者的答案是否定的 – 我们很好.

http://stackoverflow.com/questions/43244192/does-the-javascript-event-system-violates-the-lsp


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

梦断代码

梦断代码

Scott Rosenberg / 韩磊 / 电子工业出版社 / 2008.06 / 49.00元

软件乃是人类自以为最有把握,实则最难掌控的技术。本书作者罗森伯格对OSAF主持的Chandler项目进行田野调查,跟踪经年,试图借由Chandler的开发过程揭示软件开发中的一些根本性大问题。. 本书是讲一事,也是讲百千事;是写一软件,也是写百千软件;是写一群人,也是写百千万人。任何一个在软件领域稍有经验的技术人员看完本书,必掩卷长叹:做软件难。...一起来看看 《梦断代码》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具