【问题标题】:Functional Programming in Java 8Java 8 中的函数式编程
【发布时间】:2018-07-01 02:45:28
【问题描述】:

据我所知,函数式编程意味着提供不同的行为实现接口。这会比我必须创建一个新类并在其中实现该接口更好吗? 这个我不是很清楚

interface worldGreeting {
 String processName(String str);
}
public class ReadJson {

public static void main(String[] argv) throws Exception {
    worldGreeting morningGreeting = (str) -> "Good Morning " + str + "!";
    worldGreeting eveningGreeting = (str) -> "Good Evening " + str + "!";
    System.out.println(morningGreeting.processName("Waseem"));
    System.out.println(eveningGreeting.processName("Saeed"));
}

}

第二种方法是这样的

class Moring implements worldGreeting{
@Override
public String processName(String str) {
    return "Good Morning " + str + "!";
  }
  }

 class Evening implements worldGreeting{

@Override
public String processName(String str) {
    return "Good Evening " + str + "!";
  }
 }

【问题讨论】:

  • SAM 类型是一个丑陋的黑客。
  • 你应该重新考虑你的命名。约定是让类型(包括接口)以大写字母开头。此外,当与读取 Json 没有任何关系时,不要调用 ReadJson 类。除此之外,函数式编程与如何实现接口无关。但是您应该能够在示例中看到使用 lambda 表达式的明显优势……
  • 在您的情况下,唯一的优势是使用 lambda,您不必创建显式类或匿名类来实现接口。
  • @Jean-BaptisteYunès 这只是 POC 类。

标签: interface java-8 functional-programming


【解决方案1】:

单抽象方法表示法和匿名接口实现之间的区别并不重要,所以在我的代码示例中,我会更喜欢匿名接口实现。

考虑这两种不同的方式来提供类似的功能:

版本 1:类型级继承

interface Greeter {
    abstract String greet(String name);
}
class MorningGreeter implements Greeter {
    @Override public String greet(String name) {
        return "Good morning, " + name + "!";
    }
}
class EveningGreeter implements Greeter {
    @Override public String greet(String name) {
        return "Good evening, " + name + "!";
    }
}

版本 2:匿名实现

interface Greeter {
    abstract String greet(String name);
    static Greeter morningGreeter = new Greeter() {
        @Override public String greet(String name) {
            return "Good morning, " + name + "!";
        }
    };
    static Greeter eveningGreeter = new Greeter() {
        @Override public String greet(String name) {
            return "Good evening, " + name + "!";
        }
    };
}

有哪些不同之处?版本 1 添加了三个类型级别的抽象,而版本 2 仅添加了一个。此外,版本 1 允许实例化任意数量的 MorningGreeters 和 EveningGreeters,而版本 2 的编写方式是只有一个 morningGreeter 和一个 eveningGreeter

出于几个原因,我更喜欢第 2 版。

首先,没有理由创建一个以上的MorningGreeter 实例,因为任何两个实例的功能都无法相互区分:唯一的区别是它们的内存地址。我尝试只为我将多次实例化并具有不同属性的事物创建类。

其次,我个人认为MorningGreeterEveningGreeter不应该是它们自己的类型级抽象,因为它们没有给Greeter添加任何方法或字段。我试图通过它们支持的方法和字段来限制我的类型级别抽象,因为类型系统的目的是防止您在可能不支持它的对象上调用错误的方法,而Greeter 是类型级别具有签名String greet(String name) 的单一方法的对象的抽象。我觉得用完全相同的方法创建两个新的类型级抽象没有太大价值。

第三,版本 2 为这个(非常简单的)库的用户提供了一个清晰的入口点。在第 1 版中,用户要么需要grep "implements Greeter" 的所有项目文件,要么使用 IDE 魔术跳转到实现类。在版本 2 中,用户只需使用两种静态便捷方法中的任何一种创建一个欢迎程序。

我希望这能回答您的问题。我认为这是一个很好的问题,而不仅仅是个人品味问题。

【讨论】:

  • 几个反对意见:1)接口方法上的abstract关键字是多余的。 2)子类/接口实现不需要添加方法或字段才有目的。他们添加/实施行为,赋予他们目的。 3) 我认为问题在于 lambdas 与匿名类之间的区别。
  • @LarsGendner 感谢您的评论。何时子类化和何时不子类化当然是主观的。在上述情况下,我只是更喜欢匿名实现,并限制数字类型级别的抽象。这两种方法都有原因:我并不是要批评任何人的编码风格。其次,这个问题特别问“创建匿名实现者还是创建实现类更好?” (释义)所以我相信你可以原谅我在这方面阅读这个问题。最后,我知道abstract 在那里是多余的;-p 干杯 :-)
  • 我认为我们关于提问者的意思的讨论是暗示问题不清楚;-)
猜你喜欢
  • 2020-10-02
  • 2021-01-11
  • 1970-01-01
  • 2018-01-25
  • 2014-05-13
  • 1970-01-01
  • 2023-04-09
  • 2010-11-19
  • 2017-08-21
相关资源
最近更新 更多