【问题标题】:Does Java support Swift-like class extensions?Java 是否支持类似 Swift 的类扩展?
【发布时间】:2016-08-10 07:18:27
【问题描述】:

在 Swift 中,您可以创建现有类的扩展,以便在需要时向现有类添加其他功能。这也有助于避免创建现有类的子类。

我只是想知道Java中是否存在类似的功能?还是向现有 Java 类添加其他方法的唯一方法是创建现有类的子类?

【问题讨论】:

  • 不是在 Java 中。然而,并不是每个人都对 Scala 中的这个说法感到满意。因为它会妨碍可读性和可维护性。通常人们会创建一个带有函数的类,比如 XxxUtils 或 Xxxs。继承有其自身的问题(最终类,旧代码的强制过时,集中 = 只是一个扩展点)。
  • ManifoldJava 提供全面、无缝的 C# 风格的扩展方法 支持,允许您向不受控制的类添加方法,例如,java.lang.String。演示:http://manifold.systems/images/ExtensionMethod.mp4

标签: java subclass extension-methods


【解决方案1】:

不,vanilla Java 没有扩展方法。然而,Lombok 添加了许多有用的特性——包括扩展方法语法——这要归功于它的注释和字节码生成。

您可以使用其@ExtensionMethod 注释将现有的静态方法“转换”为扩展方法。静态方法的第一个参数基本上变成了this。例如,这是一个有效的 Lombok 增强 Java 代码:

import lombok.experimental.ExtensionMethod;

@ExtensionMethod({java.util.Arrays.class, Extensions.class})
public class ExtensionMethodExample {
  public String test() {
    int[] intArray = {5, 3, 8, 2};
    intArray.sort();

    String iAmNull = null;
    return iAmNull.or("hELlO, WORlD!".toTitleCase());
  }
}

class Extensions {
  public static <T> T or(T obj, T ifNull) {
    return obj != null ? obj : ifNull;
  }

  public static String toTitleCase(String in) {
    if (in.isEmpty()) return in;
    return "" + Character.toTitleCase(in.charAt(0)) +
        in.substring(1).toLowerCase();
  }
}

请注意,Lombok 扩展方法可以在 null 对象上“调用”——只要静态方法是 null 安全的,NullPointerException 就不会被抛出,因为这基本上被转换为静态方法调用。是的 - 它归结为语法糖,但我想这仍然比通常的静态方法调用更具可读性。

除此之外,您还可以使用其他具有 Java 互操作性的 JVM 语言,如果在您的项目中可以的话。例如,Kotlin 带有 extension methods functionality,以及标准库中已经定义的一些有用的扩展。这是Kotlin and Lombok comparison

【讨论】:

  • 我喜欢 lombok :) 这在 swift 中确实仍然更清晰/可读,但至少我们也可以在 Java 中做到这一点(而不是直接这样做)。
【解决方案2】:

ManifoldJava 提供全面、无缝的 C# 风格 扩展方法 支持,允许您向不受控制的类添加方法,例如 java.lang.String

演示: http://manifold.systems/images/ExtensionMethod.mp4

了解更多:
http://manifold.systems/docs.html
https://github.com/manifold-systems/manifold

【讨论】:

  • 让 lombok 跑起来很痛苦。也许流形更容易?它可以在 Eclipse 中工作吗?
  • Manifold 并不难使用,您可以轻松地将其集成到现有项目中。基本上,您为 Javac 添加 -Xplugin:Manifold arg,如果您正在使用运行时功能,请将歧管 jar 添加到您的类路径中。它完全支持 Java 8 - 11,并且与 Maven 和 Gradle 配合得很好。 IntelliJ IDEA 作为插件提供对 Manifold 的全面支持。目前没有对 Eclipse 的支持。
【解决方案3】:

Decorator Pattern 可能是最接近的匹配项。它使用接口来维护类型兼容性和组合以增强现有类的功能。它与您描述的原理不同,但可能具有相同的目的。

【讨论】:

    【解决方案4】:

    它可以在 JVM 的其他语言中完成,例如 Scala、Groovy 或 Closure。

    例如在 Groovy 中:

    List.metaClass.printSize = {
        println delegate.size()
    }
    
    [1,2,3].printSize() //prints 3
    

    在 Scala 中你可以使用implicit class

    implicit class PrefixedString(val s: String) {
       def prefix = "prefix_" + s 
    }
    
    "foo".prefix // returns "prefix_foo"
    

    请看this article.

    重要的一点是,Groovy/Scala 源代码旨在编译为 Java 字节码,以便生成的类可以在 Java 代码中使用。

    【讨论】:

    • 此外,Lombok 内部也有一些魔力,但它 Java,所以说它的“不可能”并不完全正确。
    • Scala 示例应该使用implicit classextends AnyVal
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多