Java 方法需要封闭 class 而不是内部 class 的实例

Java method that requires instance of enclosing class but not inner class

如果我有一个非静态内部 class,我知道它不能包含静态方法,因为它需要一个封闭 class 的实例才能访问。但是,有没有办法创建一个可以用外部 class 的实例引用但不能用内部实例引用的方法?大致如下:

public class Family {

  public final Set<Dog> pets = new HashSet<Dog>();

  public class Dog {
    
    public Color color;
    public int weight;
    public int height;

    public Dog(Color color, int weight, int height) {
      this.color = color;
      this.weight = weight;
      this.height = height;
      Family.this.pets.add(this);
    }

    public void addDefaultBlack() {
        new Dog(Color.BLACK, 10, 10);
    }

    public void addDefaultWhite() {
        new Dog(Color.WHITE, 5, 5);
    }

  }

}

我可以这样引用它:

Family family = new Family();
family.Dog.addDefaultBlack();

...通过要求外部 class 的实例,而不是内部实例。在这种情况下,Dog 不是静态内部 class 因为每只狗都必须属于一个家庭,但我想要一些方法可以创建具有某些默认属性的狗并将其添加到 Family 封闭 class 的对象。目前我能想到的唯一方法是创建一个枚举(例如 DefaultDogs 之类的东西)并将其作为参数传递到新的构造函数中,然后切换大小写以应用属性。这似乎有些混乱,所以我宁愿避免它。有没有办法用我展示的方法来做到这一点?正确的语法是什么?对不起,如果我在这里遗漏了一些明显的东西。

编辑:我知道我可以在外部 class 中放置一个方法,但在我看来,为了可读性和逻辑,将它保留在内部 class 中对我来说更有意义.这是完成这项工作的唯一方法吗?

addDefaultBlack 方法必须是 outer class 的实例方法,你会调用 family.addDefaultBlackDog()。可能不是您想要的。

下面就如你所愿。但是您需要将 Family class 的实例传递给用于创建 Dog class 的新实例的方法。 addDefault classes 可以声明为静态的,因此可以通过 vi Family.Dog.

间接访问它们
import java.awt.Color;
import java.util.HashSet;
import java.util.Set;

public class FamilyDemo {
    public static void main(String[] args) {
        Family family1 = new Family();
        Family family2 = new Family();
        family1.new Dog(Color.orange, 70,40);
        family2.new Dog(Color.green, 100,200);
        
        Family.Dog.addDefaultBlack(family1);
        Family.Dog.addDefaultWhite(family2);
        System.out.println(family1.pets);
        System.out.println(family2.pets);
    }
    
}

class Family {
    
    public final Set<Dog> pets = new HashSet<>();
    public class Dog {
        
        public Color color;
        public int weight;
        public int height;
        
        public Dog(Color color, int weight, int height) {
            this.color = color;
            this.weight = weight;
            this.height = height;
            pets.add(this);
        }
        
        
        public static void addDefaultBlack(Family instance) {
            instance.new Dog(Color.BLACK, 10, 10);
        }
        
        public static void addDefaultWhite(Family instance) {
            instance.new Dog(Color.WHITE, 5, 5);
        }
        
        public String toString() {
            return color + ", " + weight + ", " + height;
        }
    }
}

我考虑了更多,有一些想法供您考虑。

  • 除非您打算画宠物,否则不要使用 Color。它不适合用于描述目的。为 Color 创建一个枚举,并要求将其用作构造函数中的参数。您可以随时添加更多颜色而不影响现有的实现。
  • Dog class 更改为 Pet class。然后你可以有一个可能的宠物枚举。您甚至可以让枚举类型为宠物提供范围,以在值中强制执行不变量。例如,如果您允许 tarantula 作为宠物,您就不会希望它达到 100 磅。 (哎呀!)。只需调整枚举即可添加更多宠物。最小值和最大值以及其他值都可以指定为枚举类型的参数。
  • 最后,不仅家庭可以养宠物,单身人士甚至组织也可以。您最初问题的根源是让内部 class 将 dog 的实例添加到封闭的 class 的 Dog 集中。为什么不在 Family 之外拥有一个对其他人有用的 Pet class。您可以将其设为 PetFactory 并带有自定义设置和标准默认宠物。然后留给使用 class 将宠物添加到集合中。