04-31.eri-test 皮条客我的图书馆模式

Øriginally posted on: Big ball of mud

当您使用不拥有的库时,作为开发人员遇到的主要问题是什么? 您不能更改它们。 如果库的公共API中缺少某些内容,则没有机会对其进行扩展。 使用一些出色的旧的面向对象编程,您可以通过编写许多样板代码来克服此问题。 在JVM生态系统中,诸如Scala,Kotlin或Groovy之类的现代编程语言试图为库扩展Pimp My Library Pattern提供解决方案。 走吧,看看我在说什么。

The problem

让我们从一个非常极端的例子开始。 假设您要添加一个方法整数Java中的类型,可让您将int转换为java.time.期类。 对于那些不知道这门课的人,期代表时间,使用天,月,年。

我们要实现的全部目标如下。

final Period days = Integer.valueOf(42).days();

在诸如Scala或Kotlin之类的更进化的语言中,上面的陈述将如下所示。

val days = 42.days;

In Java, you have no many such possibilities to achieve the goal. Since we cannot nor we want to modify directly the 一世nteger type, and we do not want to use inheritance on a concrete type, the only remaining possibility is to implement a method somewhere that receives in input an 一世nteger and returns a Period.

class Integer2Period {
    private Integer integer;
    Integer2Period(int integer) {
        this.integer = integer;
    }
    Period days() {
        return Period.ofDays(integer);
    }
}
var days = new Integer2Period(42).days();

嗯 我们用了包装纸或对象适配器模式的某些差异,但与最初的目标相距甚远。

让我们看看现代的JVM语言(例如Kotlin,Scala和Groovy)如何解决这个问题。

Scala

Scala was the language that first introduced the Pimp My Library pattern. The pattern was introduced by the Scala language's dad, Martin Odersky, in his article Pimp my Library, in the far 2006.

该模式允许在不使用任何形式的继承的情况下向其扩展类型添加方法。 使用该模式,我们可以向整数类型而不扩展。

Scala语言通过以下方式实现模式隐式转换。 首先,我们需要声明一个隐含的类,允许编译器将我们的主要类型转换为新类型,从而添加我们想要的方法。 在我们的例子中,主要类型是整数类型。

package object extension { 
  implicit class ExtendedInt(val integer: Int) extends AnyVal {
    def days = Period.ofDays(integer)
  }
}

包装内延期,或在任何包中,显式导入包延期,我们可以使用类型中定义的方法Extended整数作为为整数类型。

val days = 42.days;

魔术的窍门有两个:

  1. 包对象中隐式类型的声明会强制编译器自动导入ExtendedInt输入属于它的所有文件。班级ExtendedInt被声明为隐含的。班级ExtendedInt是该类型的子类AnyVal。 From Scala 2。10, extending from AnyVal allows the compiler to perform some code optimisations。 It's called 自定义值类。

如果我不解释javap错误地命令。类由Scala编译器生成的文件,Scala将转换为隐式类的字节码,类似于包装纸我为Java提供的方法。

public final class org.rcardin.extension.package$ExtendedInt {
  public int integer();
  public java.time.Period days();
  public int hashCode();
  public boolean equals(java.lang.Object);
  public org.rcardin.extension.package$ExtendedInt(int);
}

方法整型 整型eger()是私有属性的获取者,该类的构造函数将类型为变量的输入作为输入整型。 反编译的隐式Scala类具有与Java类相同的结构Integer2Period。

The standard library extensively uses the pattern. All the type defined with the suffix Ops implement the pattern. Have a look at the StringOps type for an example.

Kotlin

此外,基于JVM的新手语言Kotlin也实现了皮条客我的图书馆图案。 在Kotlin lang语中,它称为模式实现扩展功能。 该模式是用该语言引入的,目的是为了与Kotlin开发人员可以使用的大多数库是Java而不是Kotlin进行比较。

声明一个扩展功能不如Scala语言(:O)中使用的语法那么冗长。

fun Integer.days(): Period = Period.ofDays(this)

在我们的示例中,整数类型也称为接收器类型。 鉴于这个分配符号右侧的参考称为接收对象。 的这个 reference refers to the integer instance on which the extension method is called. To preserve encapsulation, you can access only to the public methods of the 接收对象.

默认情况下,编译器不导入扩展方法。 与其他Kotlin实体一样,您需要在显式使用它们之前将其导入。

在后台,编译器将每个扩展方法转换为静态的接收者对象作为其第一个参数的方法。 封闭类的名称等于声明扩展功能的文件的名称。

假设我们声明了整数天函数IntegerUtil。kt中的文件,然后Kotlin编译器将我们的代码编译为一个名为class的静态方法整数实用程序。

class IntegerUtilKt {
    public static Period days(Integer receiver) {
        return Period.ofDays(receiver);
    }
}

它与我们为Java语言提供的解决方案非常相似。

Kotlin编译器对扩展函数执行的翻译使我们也可以在可为空的类型上调用它们。 在作为第一个参数传递给静态方法的接收器对象上,不会直接调用任何方法。

因此,扩展功能和Kotlin类型系统使我们可以声明以下内容。

fun String?.isNullOrBlank(): Boolean = this == null || this.isBlank()

您可以安全地在if语句,控制可为空的对象是否包含一个空值参考与否。

val possiblyEmptyString: String? = // Obtaining the string reference
if (possiblyEmptyString.isNullOrBlank()) { // No NullPointerException!!!
    // Do something smart
}

太棒了 Kotlin每天都继续让我感到惊讶。

Conclusions

有时,一个库包含了几乎所有您需要的内容,但是缺少一些您想要的功能。 在这种情况下,不可能使用常规的面向对象机制进行扩展。 许多基于JVM的语言使您可以实现无需修改即可将所需方法添加到现有库的目标。

的皮条客我的图书馆模式是使魔术发生的机制。 Scala用途隐式对象以及实现这种模式的惯例。 相反,Kotlin具有更自然的方法,该方法与有关空引用处理的Kotlin类型系统很好地集成在一起。

Moreover, let's say that also Groovy implements the pattern, using Extensions and Categories.

您在哪里Java? 你会参加聚会吗?


If you want, download the code of the Scala example from my repository on GitHub: pimp-my-library.

References

from: https://dev.to//riccardo_cardin/the-pimp-my-library-pattern-8bl

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值