使用可变参数在 class 中创建对象

Using varargs to create an object in a class

我正在尝试创建一个名为 GameCharacter 的 class,它代表一个游戏角色并且具有 以下属性: • 名称(字符串) • 权力(一组权力对象)

如何在 class 中设置这样的对象?构造函数必须使用可变参数,因为 Power 可以有不同的参数。这是我的尝试,但显然是行不通的! 这是我没有解决方案的过去 2019 年作业问题,我是 java 的初学者。任何有助于理解这一点的帮助都将不胜感激!

    class GameCharacter{
    private String name;
    private int cost;
    class Powers{
        public Powers(Power... powers) {
            for (int i: powers) {
                this.i = powers
                
            }
        }
    }
    
    //constructor
    public GameCharacter(String name, int cost, Power... powers) {
        this.name = name;
    
    }
}

你的代码有很多难点:

  1. 错误的 foreach 声明。
  2. 不同的类型和方法参数名称。
  3. 缺少类型为 Power into class Powers 的字段。

我猜你可能想做什么,但你的问题需要适度。

class GameCharacter{

    private String name;

    private int cost;

    class Powers{
        
        public Powers(Power... powers) {
            for (Power i: powers) {
                //what initialize do you want?  
            }
        }
    }

    //constructor
    public GameCharacter(String name, int cost, Powers powers) {
        this.name = name;    
    }
    
    class Power{
        
    }
}

对于一组 Power 个对象,使用 Set < Power >

如果要跟踪一组 Power 个对象,请使用 Set class。不需要可变参数,只需传递一个 Set 对象。

为了简单起见,让我们使用 Java 16 中的 Record 功能。编译器隐式创建构造函数、getter、equalshashCode,和 toString。当 class 的主要目的是透明且不变地携带数据时,记录是合适的。使用记录使这个示例代码更短。

package work.basil.example.Game;

import java.util.Set;

public record GameCharacter (String name, Set <Power> powers)
{
}

对于不可修改的 Set,请使用 Set.of 方法。

package work.basil.example.Game;

public record Power(String description)
{
}
package work.basil.example.Game;

import java.util.Set;

public class App
{
    public static void main ( String[] args )
    {
        App app = new App();
        app.demo();
    }

    private void demo ( )
    {
        GameCharacter susan = new GameCharacter(
                "Susan" ,
                Set.of(
                        new Power( "invisibility" ) ,
                        new Power( "force field" )
                )
        );
        GameCharacter ben = new GameCharacter(
                "Ben" ,
                Set.of(
                        new Power( "physical strength" ) ,
                        new Power( "rock-like hide" )
                )
        );

        System.out.println( "susan = " + susan );
        System.out.println( "ben = " + ben );
    }
}

当运行:

susan = GameCharacter[name=Susan, powers=[Power[description=force field], Power[description=invisibility]]]
ben = GameCharacter[name=Ben, powers=[Power[description=rock-like hide], Power[description=physical strength]]]

如果您要定义常规 classes 而不是 record,您将在 GameCharacter class 上定义两个成员字段:String名称,Set < Power > powers 用于收集 Power 个对象。你会添加一个构造函数,为这两个字段接受两个参数。

package work.basil.example.Game;

import java.util.Objects;
import java.util.Set;

public final class GameCharacter
{
    // Member fields
    private final String name;
    private final Set < Power > powers;

    // Constructor
    public GameCharacter ( String name , Set < Power > powers )
    {
        this.name = name;
        this.powers = powers;
    }

    public String name ( ) { return name; }

    public Set < Power > powers ( ) { return powers; }

    @Override
    public boolean equals ( Object obj )
    {
        if ( obj == this ) return true;
        if ( obj == null || obj.getClass() != this.getClass() ) return false;
        var that = ( GameCharacter ) obj;
        return Objects.equals( this.name , that.name ) &&
                Objects.equals( this.powers , that.powers );
    }

    @Override
    public int hashCode ( )
    {
        return Objects.hash( name , powers );
    }

    @Override
    public String toString ( )
    {
        return "GameCharacter[" +
                "name=" + name + ", " +
                "powers=" + powers + ']';
    }
}

可变参数

现在我们可以回到您的具体问题:如何在构造函数中处理可变参数。

这里我们向上面看到的 class 添加第二个构造函数。第二个采用 Power.

类型的可变参数

可变参数作为 Power 个对象的数组到达。我们可以使用 for-each 语法循环该数组的元素。我们将每个元素添加到我们选择的新 Set 实现中,在本例中为 HashSet class.

    public GameCharacter ( String name , Power... powers )
    {
        this.name = name;
        Set<Power> s = new HashSet <>();    // New empty `Set` implementation.
        for ( Power power : powers )        // `powers` is the varargs array of `Power` objects.
        {
            s.add(power);                   // Add each element of array, each `Power` object, to our `Set` collection.
        }
        this.powers = s;
    }

为了使用这个构造函数,我们调整 App class 以放弃对 Set.of.

的调用
package work.basil.example.Game;

import java.util.Set;

public class App
{
    public static void main ( String[] args )
    {
        App app = new App();
        app.demo();
    }

    private void demo ( )
    {
        GameCharacter susan = new GameCharacter(
                "Susan" ,
                new Power( "invisibility" ) ,
                new Power( "force field" )
        );
        GameCharacter ben = new GameCharacter(
                "Ben" ,
                new Power( "physical strength" ) ,
                new Power( "rock-like hide" )
        );

        System.out.println( "susan = " + susan );
        System.out.println( "ben = " + ben );
    }
}

这是我们修改后的 GameCharacter 的整个 class 的源代码,现在提供两个构造函数。

package work.basil.example.Game;

import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

public final class GameCharacter
{
    // Member fields
    private final String name;
    private final Set < Power > powers;

    // Constructors

    // First constructor
    public GameCharacter ( String name , Set < Power > powers )
    {
        this.name = name;
        this.powers = powers;
    }

    // Second constructor
    public GameCharacter ( String name , Power... powers )
    {
        this.name = name;
        Set<Power> s = new HashSet <>();
        for ( Power power : powers )
        {
            s.add(power);
        }
        this.powers = s;  
    }

    // Getters

    public String name ( ) { return name; }

    public Set < Power > powers ( ) { return powers; }

    // `Object` overrides

    @Override
    public boolean equals ( Object obj )
    {
        if ( obj == this ) return true;
        if ( obj == null || obj.getClass() != this.getClass() ) return false;
        var that = ( GameCharacter ) obj;
        return Objects.equals( this.name , that.name ) &&
                Objects.equals( this.powers , that.powers );
    }

    @Override
    public int hashCode ( )
    {
        return Objects.hash( name , powers );
    }

    @Override
    public String toString ( )
    {
        return "GameCharacter[" +
                "name=" + name + ", " +
                "powers=" + powers + ']';
    }
}

提示:如果您希望成员字段 powers 成为不可修改的集合,您可以将第二个构造函数缩减为:

    // Second constructor
    public GameCharacter ( String name , Power... powers )
    {
        this.name = name;
        this.powers = Set.of( powers ) ;  // Make an unmodifiable set from the varargs array.
    }