如何在Java或C#等静态类型语言中避免参数顺序依赖

时间:2016-05-13 04:18:28

标签: java c#

我来自Python,Ruby和PHP世界,我尝试遵循的一种技术是从我的代码中删除参数顺序依赖项。这是在Ruby中实现的这种技术的简短演示:

class Gear
    attr_reader :chainring, :cog, :wheel
    def initialize(args)
       @chainring = args[:chainring]
       @cog = args[:cog]
       @wheel = args[:wheel]
    end
    ...
end

Gear.new(
   :chainring => 52,
   :cog => 11,
   :wheel => Wheel.new(26, 1.5)).gear_inches

正如您所看到的,客户端代码不需要知道初始化Gear实例的参数顺序,我喜欢这样。但现在我只是想知道如何在Java这样的静态类型语言中实现同样的东西,我也想知道人们是否试图在这种语言中使用这些技术。如果有人可以分享他们的经验并展示一些演示代码(让它用Java,C#等),那就太好了。

4 个答案:

答案 0 :(得分:5)

您不必遵守C#中的参数顺序。如果您知道参数名称,则可以使用参数名称,冒号和值来利用named and optional arguments

    static void Main(string[] args)
    {
        var variable1 = "1";
        var variable2= 90056;
        var variable3 = 'u';

        // random order
        TestMethod(arg3: variable3, arg1: variable1, arg2: variable2);

        // you can even omit some argument
        TestMethod(arg2: variable2);
    }

    private static void TestMethod(string arg1 = null, int arg2 = 0, char arg3 = '\0')
    {
        Console.WriteLine(arg1);
        Console.WriteLine(arg2);
        Console.WriteLine(arg3);

        Console.ReadKey();
    }

我相信Xiaoy312的答案是你正在寻找的,但是我会把它留在这里以防以后有人对它感到好奇。

答案 1 :(得分:3)

如果仅用于创建新对象,则可以使用Object Initializer

public class Gear
{
    public int Chainring { get; set; }
    public int Cog { get; set; }
    public int Wheel { get; set; }
}

// ...
var gear = new Gear
{
    // could be in any order, 
    Cog = 11,
    Chainring = 52,
}

关于方法论点,请查看KSid在Named and Optional Arguments上的答案。

答案 2 :(得分:2)

这是一种语言功能,它存在于某些但不是所有静态类型的语言中。该功能在Java中不存在,但它存在于Scala中,并且存在于C#中(参见KSib的回答)。

关于您的技术,有一些好处。

  1. 即使更改参数顺序,您的代码也能正常工作
  2. 通过明确您的参数来改进编译器安全性(例如,如果参数不存在,编译器错误)
  3. 在方法存在多个重载的情况下提高了可读性
  4. 在存在多个相同类型的参数的情况下提高可读性/可维护性
  5. 缺点是

    1. 您与参数名称相关联
    2. 参数名称更可能在次要修订版本中更改,但参数顺序不应在次要修订版本中更改
    3. 更详细的代码

答案 3 :(得分:2)

试试Lombok

在Java中,方法中的参数顺序非常强制,除非您在讨论命令行应用程序,为此我建议使用Apache CLI。如果您正在谈论构造函数,那么Lombok对您来说是一个很好的库。它实现了一个构建器模式,然后您可以根据已声明的任意数量的私有变量以及您希望的任何顺序创建实例。

说你有:

@Builder
public class MySuperClasse {

private int mySuperInt;

private String mySuperString;

private Date mySuperDate;

}

然后您可以像这样构建您的实例:

MySuperClass super = MySuperClass.builder().mySuperString(string).mySuperInt(int).mySuperDate(date).build();

或者你可以做

MySuperClass super = MySupeClass.builder().mySuperDate(date).build();

基本上发生的事情是,当您使用@Builder注释您的类时,Lombok会隐式创建构建器以及创建实例的不同方法。它的美妙之处在于它完全符合您的要求,但却以略微不同的方式。