You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Scala DSL:如何实现多命令链式调用的and关键字语法?

实现A doX and doY B风格的布尔方法链式判断

当然可以实现这种简洁的语法!核心思路是通过链式调用+中间状态对象来封装原始对象A和要执行的方法序列,避免重复写A doX B && A doY B这种冗余代码。下面分几种常见语言给出具体实现,核心逻辑通用,能支持任意多方法的and串联:

核心设计思路

  1. 让对象的布尔方法(比如doX、doY)返回一个中间链式对象,这个对象保存原始对象A和当前已选择的方法。
  2. 给中间对象添加and方法,用来接收下一个要执行的方法,更新方法序列并返回自身(保持链式)。
  3. 最后提供一个入口(比如函数调用、专用方法)接收对象B,依次执行所有方法并返回所有结果的逻辑与(&&)结果。

这种方案完全不依赖隐式转换,而且对任意数量的方法都通用,扩展性极强。


JavaScript实现(最贴近自然语法)

利用Proxy可以实现几乎和A doX and doY B一致的语法:

class MyObject {
  constructor(value) {
    this.value = value;
  }

  // 实际业务逻辑方法
  _doX(other) {
    return this.value > other.value;
  }

  _doY(other) {
    return this.value < other.value * 2;
  }

  // 封装成链式调用入口
  get doX() {
    return new ChainProxy(this, '_doX');
  }

  get doY() {
    return new ChainProxy(this, '_doY');
  }
}

class ChainProxy {
  constructor(sourceObj, methodName) {
    this.source = sourceObj;
    this.methods = [methodName];
    
    // 用Proxy实现`and.doY`的语法
    return new Proxy(this, {
      get(target, prop) {
        if (prop === 'and') {
          return new Proxy({}, {
            get(_, method) {
              target.methods.push(method);
              return target;
            }
          });
        }
        return target[prop];
      },
      // 重载调用操作符,接收B对象
      apply(target, _, args) {
        const [other] = args;
        return target.methods.every(method => target.source[method](other));
      }
    });
  }
}

// 使用示例
const A = new MyObject(5);
const B = new MyObject(3);

// 完美贴近需求语法:A doX and doY B
const result = A.doX.and._doY(B);
console.log(result); // true

Java实现(静态类型语言方案)

Java是静态类型语言,需要用泛型和函数式接口实现链式调用:

import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;

class MyObject {
    private int value;

    public MyObject(int value) {
        this.value = value;
    }

    // 实际业务方法
    public boolean doX(MyObject other) {
        return this.value > other.value;
    }

    public boolean doY(MyObject other) {
        return this.value < other.value * 2;
    }

    // 返回链式对象入口
    public BooleanChain doX() {
        return new BooleanChain(this, this::doX);
    }

    public BooleanChain doY() {
        return new BooleanChain(this, this::doY);
    }
}

class BooleanChain {
    private MyObject source;
    private List<Function<MyObject, Boolean>> methods;

    public BooleanChain(MyObject source, Function<MyObject, Boolean> firstMethod) {
        this.source = source;
        this.methods = new ArrayList<>();
        this.methods.add(firstMethod);
    }

    // 串联下一个方法
    public BooleanChain and(Function<MyObject, Boolean> nextMethod) {
        this.methods.add(nextMethod);
        return this;
    }

    // 执行所有方法并返回结果
    public boolean applyTo(MyObject other) {
        return this.methods.stream().allMatch(method -> method.apply(other));
    }
}

// 使用示例
public class Main {
    public static void main(String[] args) {
        MyObject A = new MyObject(5);
        MyObject B = new MyObject(3);
        
        boolean result = A.doX().and(A::doY).applyTo(B);
        System.out.println(result); // true
    }
}

C#实现(利用索引器简化语法)

C#可以用索引器来模拟B的传入,让语法更简洁:

using System;
using System.Collections.Generic;
using System.Linq;

public class MyObject
{
    public int Value { get; set; }

    // 实际业务方法
    public bool DoX(MyObject other) => this.Value > other.Value;
    public bool DoY(MyObject other) => this.Value < other.Value * 2;

    // 返回链式对象入口
    public BooleanChain<MyObject> DoX() => new BooleanChain<MyObject>(this, this.DoX);
    public BooleanChain<MyObject> DoY() => new BooleanChain<MyObject>(this, this.DoY);
}

public class BooleanChain<T>
{
    private readonly T _source;
    private readonly List<Func<T, bool>> _methods;

    public BooleanChain(T source, Func<T, bool> firstMethod)
    {
        _source = source;
        _methods = new List<Func<T, bool>> { firstMethod };
    }

    // 串联下一个方法
    public BooleanChain<T> And(Func<T, bool> nextMethod)
    {
        _methods.Add(nextMethod);
        return this;
    }

    // 用索引器接收B对象,执行所有方法
    public bool this[T other] => _methods.All(method => method(other));
}

// 使用示例
class Program
{
    static void Main()
    {
        var A = new MyObject { Value = 5 };
        var B = new MyObject { Value = 3 };
        
        bool result = A.DoX().And(A.DoY)[B];
        Console.WriteLine(result); // True
    }
}

扩展说明

  • 这些方案都支持无限串联方法,比如A doX and doY and doZ B只需要在链式调用中继续添加.and(doZ)即可。
  • 完全不需要修改原有业务方法的逻辑,只需要封装一层链式入口即可,对原有代码侵入性极低。
  • 如果需要实现or逻辑,只需要把allMatch(或every)改成anyMatch(或some)即可,非常灵活。

内容的提问来源于stack exchange,提问作者THIS USER NEEDS HELP

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:18:01