隐藏变异子,需要澄清

发布于 2024-12-06 05:36:58 字数 559 浏览 1 评论 0原文

假设您有一个 Dog 类,此外

public class Dog {

    private String name;
    private double age;

    // some setters
    // some getters

,您还有一个 DogHandler 类,它创建 Dog d 的实例并将其传递给Owner

我想,我可以

......在将 Dog 传递给 Owner 之前复制它,但这是一项昂贵的操作,我宁愿避免它。

...提出一个 Dog 实现的接口,其中仅包含 getter,将 Dog 转换为该接口并传递结果

...在构造函数中初始化可设置变量,然后根本不允许更改对象的此实例

还有其他方法可以确保对象的接收者无法修改它吗?

如何获取包含某些数据的简单 bean 并将其设置为只读?

Suppose you have a class Dog, that has

public class Dog {

    private String name;
    private double age;

    // some setters
    // some getters

Additionally, you have a class DogHandler, that makes an instance of the Dog d and passes it to Owner

I suppose, i can

... make a copy of a Dog before passing it to Owner, but that's an expensive operation and i'd rather avoid it.

... come up with an interface that Dog implements which contains getters only, cast Dog to that interface and pass the result along

... initialize settable variables in a constructor and simply not allow changes for this instance of an object

Are there any other ways to make sure receiver of the object cant modify it?

How do you take a simple bean containing some data and make it read-only?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

花开浅夏 2024-12-13 05:36:59

这可以通过几种方法来实现,我可以向您推荐其中 2 种:

a)带有 getters 的接口是个好主意

b)从 Dog 创建派生类,该派生类阻止了 setters 方法,如下所示:

class UnmodifiedDog extends Dog {
    public UnmodifiedDog(double age, String name) {
        super.setAge(age);
        super.setName(name);
    }
    @Override
    public void setAge(double age) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void setName(String name) {
         throw new UnsupportedOperationException();
    }   
}

在 DogHandler 中:

Dog createDog() {
    return new UnmodifiedDog(10, "Fido");
}

您可以将其传递给所有者:

owner.receiveDog(dogHandler.createDog());

This can be achieved in few ways, I can propose you 2 of them:

a) interface with getters is good idea

b) create derived class from Dog which has setters method blocked, like this:

class UnmodifiedDog extends Dog {
    public UnmodifiedDog(double age, String name) {
        super.setAge(age);
        super.setName(name);
    }
    @Override
    public void setAge(double age) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void setName(String name) {
         throw new UnsupportedOperationException();
    }   
}

In DogHandler:

Dog createDog() {
    return new UnmodifiedDog(10, "Fido");
}

and you can pass this to the Owner:

owner.receiveDog(dogHandler.createDog());
長街聽風 2024-12-13 05:36:59

您在问题中提到的方法几乎是使 Dog 不可变所采取的标准步骤。唯一的其他技巧是强制不能通过将类声明为 final 来覆盖 Dog

The approaches you mention in the question are pretty much the standard steps to take to make Dog immutable. The only other tip would be to mandate that Dog cannot be overridden by declaring the class to be final.

囚你心 2024-12-13 05:36:59

在这里提到的解决方案中,您还可以利用可见性修饰符。如果 DogOwner 位于不同的包中,您可以将修改器的可见性设置为默认(包)范围或受保护范围。

这将允许您将 DogDogHandler 保留在同一个包中(因此允许它们相应地改变 Dog 对象),同时保持Owner 对象是分开的(因此防止它们对 Dog 对象进行任何修改)。

Among the solutions mentioned here, you can also take advantage of visibility modifiers. If Dog and Owner are in separate packages, you can set the visibility of the mutators to default (package) scope or protected scope.

This will allow you to keep Dog and DogHandler in the same package (and therefore allow them both to mutate the Dog object accordingly), while keeping Owner objects separate (and therefore preventing them from making any modification to the Dog objects).

谜兔 2024-12-13 05:36:59

以下是使用接口和包访问设置器的示例。


package blah.animal;
public interface Dog
{
  double getAge();
  String getName();
}

package blah.animal;
public class DogImpl implements Dog
{
  private double age; // double seems wrong for age.
  private String name;

  ... getters (defined by Dog interface)

  // package access setters.
  void setAge(double newValue)
  {
    age = newValue;
  }

  void setName(String newValue)
  {
    name = newValue;
  }

  package blah.animal;
  public class DogHandler
  {
    public static Dog newDog(double age, String name)
    {
      Dog returnValue = new DogImpl();
      returnValue.setAge(age);
      returnValue.setName(name);

      return returnValue;
    }
  }

  package.blah.somethingelse;
  public class Blam
  {
    private Dog myDog;

    public Blam()
    {
      myDog = DogHandler.newDog(1.4D, "Tippy");
    }
  }

Here is an example using an interface and package access setters.


package blah.animal;
public interface Dog
{
  double getAge();
  String getName();
}

package blah.animal;
public class DogImpl implements Dog
{
  private double age; // double seems wrong for age.
  private String name;

  ... getters (defined by Dog interface)

  // package access setters.
  void setAge(double newValue)
  {
    age = newValue;
  }

  void setName(String newValue)
  {
    name = newValue;
  }

  package blah.animal;
  public class DogHandler
  {
    public static Dog newDog(double age, String name)
    {
      Dog returnValue = new DogImpl();
      returnValue.setAge(age);
      returnValue.setName(name);

      return returnValue;
    }
  }

  package.blah.somethingelse;
  public class Blam
  {
    private Dog myDog;

    public Blam()
    {
      myDog = DogHandler.newDog(1.4D, "Tippy");
    }
  }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文