简体   繁体   English

Java 约定:在类中使用 getter/setter?

[英]Java Conventions: use getters/setters WITHIN the class?

My professor really emphasizes protecting against privacy leaks by always using accessors and mutators to access private instance variables;我的教授确实强调通过始终使用访问器和修改器来访问私有实例变量来防止隐私泄漏; however, do I have to use the getters/setters of a class within the class?但是,我是否必须在类中使用类的 getter/setter?

So for instance, if I have the following class:例如,如果我有以下课程:

public class Person 
{
    private String name;
    private int age;
}

and I want to write a toString() method for it.我想为它编写一个 toString() 方法。 Can I just write:我可以只写:

public String toString()
{
    return name + " " + age;
}

OR do I need to do something like this:或者我需要做这样的事情:

public String toString()
{
    return this.getName() + " " + this.getAge();
}

You CAN do either one.你可以做任何一个。 However, your professor might appreciate using the methods instead of the direct access.但是,您的教授可能会喜欢使用这些方法而不是直接访问。 Here's why.这是为什么。

Let's say you have a class like this:假设你有一个这样的类:

class SomeClass {
    private int someValue;
    private String someString;

    public SomeClass(int someValue, String someString) {
        this.someValue = someValue;
        this.someString = someString;
    }

    public int someValue() {
        return this.someValue;
    }

    public String someString() {
        return this.someString;
    }

    public String toString() {
        return someValue + ": " + someString;
    }

}

It's pretty straightforward, right?这很简单,对吧? Well, what if all of a sudden we want to CHANGE the implementation of how we calculate someValue , and base it off of someString :好吧,如果突然间我们想改变计算someValue的实现方式,并以someString基础怎么someString

public int someValue() {
    int value = 0;
    for(int i = 0; i < someString.length; i++) {
         if(someString.charAt(i) == ' ') value++;
    }
    return value;
}

Now you also have to change every place where variable someValue was used.现在您还必须更改使用变量someValue每个地方。

So if you want to make the code easier to maintain in the long run, use the methods calls.因此,如果您想让代码从长远来看更易于维护,请使用方法调用。 This way when you code changes on you (and trust me, it changes all the time) you only have to change it in one spot instead of two.这样,当您对自己的代码进行更改(相信我,它一直在更改)时,您只需在一处而不是两个处进行更改。

And yes, you would want to use a method call in getting someString instead of the direct access in the last method :-)是的,您可能希望在获取someString使用方法调用,而不是在最后一个方法中直接访问 :-)

When I design a class I try to make a clear distinction between the inside (implementation details) and the outside (the interface exposed to the world).当我设计一个类时,我试图明确区分内部(实现细节)和外部(暴露给世界的接口)。 Getters and setters provide a convenient place to convert values between the form in which they are stored in the object's instance members and the form in which the outside world sees them. getter 和 setter 提供了一个方便的地方,可以在它们存储在对象实例成员中的形式和外部世界看到它们的形式之间转换值。 Using getters and setters internally would muck that up, because they'd be getting used by both the inside and outside.在内部使用 getter 和 setter 会搞砸,因为它们会被内部和外部使用。

If you find yourself wanting to hide part of a class from another part of the same class, consider breaking off the part you want to hide into its own class.如果您发现自己想对同一类的另一部分隐藏某个类的一部分,请考虑将要隐藏的部分拆分到它自己的类中。

It's normally not a good idea, for a number of reasons:这通常不是一个好主意,原因有很多:

  • You may not even want accessors for all fields您甚至可能不需要所有字段的访问器
  • Some accessors may make a defensive copy so not to expose internal state, this is normally unnecessary within the class where you know that you are not going to modify it - or plain wrong if you know you ARE going to modify it一些访问器可能会进行防御性复制,以免暴露内部状态,这通常在您知道不会修改它的类中是不必要的 - 或者如果您知道要修改它则完全错误
  • It makes debugging more annoying, because you have to follow the getters / setters它使调试更加烦人,因为您必须遵循 getter / setter
  • It makes reading the code harder in most IDEs, since most of them color fields differently than local variables它使大多数 IDE 中的代码更难阅读,因为大多数 IDE 的颜色字段与局部变量不同

... but as always, there are exceptions. ...但一如既往,也有例外。 Some setters may have side-effects (for example setting a second value) that you WANT to execute, then it might be better to use the setter.某些 setter 可能具有您想要执行的副作用(例如设置第二个值),那么最好使用 setter。 Also, if you design your class for inheritance, it may be better to go via an accessor if you want the subclass to be able to alter the behavior.此外,如果您将类设计为继承,如果您希望子类能够改变行为,最好通过访问器。

In general, no.一般来说,没有。 If your getter returns something other than the value of the field then you should use the method, but in that rare case your method should have a more descriptive name.如果您的 getter 返回的不是该字段的值,那么您应该使用该方法,但在这种极少数情况下,您的方法应该具有更具描述性的名称。 For a bad example, if you have:举个坏例子,如果你有:

public void setName(String name)
{
  _name = name;
}

and your getter returned something else, like你的吸气剂返回了别的东西,比如

public String getName()
{
  return _name.toUpperCase();
}

then yes, you should use the getter.那么是的,你应该使用吸气剂。 It would be better, though, to have a more descriptive name for that getter:不过,为那个 getter 取一个更具描述性的名称会更好:

public String getNameAsUppercase()
{
  return _name.toUpperCase();
}

You can use the accessors and mutators, but its a messy standard to follow.可以使用访问器和修改器,但要遵循的标准很混乱。

It clutters up your code and confuses anyone trying to read it thinking it might not be a part of your class.它弄乱了您的代码,并使任何试图阅读它的人都感到困惑,认为它可能不是您的课程的一部分。

Basically, just access the variables directly from inside your class, and indirectly from anywhere else.基本上,只需直接从您的类内部访问变量,并从其他任何地方间接访问变量。

No, you don't.不,你没有。 You can access any variables, private, public or protected, from within the class.您可以从类中访问任何变量,私有的、公共的或受保护的。

Here are some tables to help you:以下是一些可以帮助您的表格:

在此处输入图片说明

Source: Java Tutorials 来源:Java 教程

On the flip side, consider it from a design standpoint.另一方面,从设计的角度考虑。 One of the motivations for getters/setters is that the underlying data storage can change and things that implement the class won't need to be changed since it is encapsulated. getter/setter 的动机之一是底层数据存储可以更改,并且实现类的东西不需要更改,因为它是封装的。

So, keeping that in mind, using getters/setters within the class makes future changes easier.因此,记住这一点,在类中使用 getter/setter 可以使将来的更改更容易。 Instead of having to find all the places that alter the member directly, you just have to change the getter/setter.您不必直接查找所有更改成员的位置,而只需更改 getter/setter。 Depending on the complexity of the class, this may significantly reduce the amount of work it takes to change the storage members.根据类的复杂性,这可能会显着减少更改存储成员所需的工作量。

For example, let's assume you start out with the age variable in years.例如,假设您从以年为单位的年龄变量开始。 Then you decide later to store it as seconds for some reason.然后您决定稍后出于某种原因将其存储为秒。 But you want to always print it in years anyway.但是无论如何,您都希望在几年后始终打印它。 So in your example, you could do the math in your toString() function (and anywhere else that wants years as the units) or you can just change the math in the getAge() routine to return years from the seconds and nothing else has to change.因此,在您的示例中,您可以在 toString() 函数(以及其他任何需要以年为单位的地方)中进行数学运算,或者您可以更改 getAge() 例程中的数学以从秒中返回年数,而没有其他任何东西改变。

Obviously that example is a bit trivial.显然,这个例子有点微不足道。 The more complicated the class, the more useful it is to use getters/setters within it.类越复杂,在其中使用 getter/setter 就越有用。

If your class (or the accessor methods in question) is not final , then you should definitely use the accessor methods.如果您的类(或有问题的访问器方法)不是final ,那么您绝对应该使用访问器方法。

If another class extends yours and overrides those accessors, your class should use the overridden accessors.如果另一个类扩展了您的类并覆盖了这些访问器,则您的类应该使用覆盖的访问器。 If this would break your superclass, then your superclass is designed incorrectly;如果这会破坏您的超类,那么您的超类设计不正确; prevent those accessors from being overridden with final , or change the design of your class.防止这些访问器被final覆盖,或更改类的设计。

If exists getters and setters, then should be used always even inside class.如果存在 getter 和 setter,则即使在类内部也应始终使用。 Of course if getter and setter do something more in method then it must be considered if it fullfils the needs.当然如果 getter 和 setter 在方法上做了更多的事情,那么必须考虑它是否满足需求。

Should be used not means must be used.应该使用不是意味着必须使用。 Property can be used directly ( only inside class if property is private - and should be ) but in good practice is to use getter and setter.可以直接使用属性(如果属性是私有的,则只能在类内部使用 - 并且应该是),但良好的做法是使用 getter 和 setter。

So using property directly is possible, but I recommend use get and set because it give more flexibility and can do something more than tipical assign or get.所以直接使用属性是可能的,但我建议使用getset因为它提供了更大的灵活性并且可以做比典型的分配或获取更多的事情。

For example if in first place setter only sets something, but after a while setter is changed to do something more.例如,如果首先 setter 只设置一些东西,但一段时间后 setter 被更改为做更多的事情。

 setName(name){

     this.name=name;
 }

So in code setName("John");所以在代码中setName("John"); is equal name="John" .等于name="John" But imagine that after a while we want to set another property when name is set:但是想象一下,过了一会儿我们想在设置name时设置另一个属性:

 setName(name){

     this.name=name;
     this.nameIsSet=true;
 }

another example ( Listener pattern ) :另一个例子(监听器模式)

setName(name){

     this.name=name;
     this.listener.nameChanged(this.name); //we call listener that variable changed
 }

Then programmer needs to find every assigment like name="John" in class and refactor it to new behavior.然后程序员需要在类中找到像name="John"这样的每个赋值并将其重构为新的行为。 If only setName is used then no code change must be done.如果仅使用setName ,则无需更改代码。

Of course everything depends from need and is possible that setting, getting property from outside do something more and different and it not fullfils our need inside class.当然,一切都取决于需要,并且有可能设置,从外部获取财产会做更多不同的事情,并且不能满足我们在课堂上的需要。

No you can use directly your instance variables inside the class, you're not violating any "rule".不,您可以直接在类中使用您的实例变量,您没有违反任何“规则”。 Getters and setters are mandatory for others classes to access instance variables of a class to not violate the encapsulation principle (which is quite important in OO programming).其他类必须使用 getter 和 setter 来访问类的实例变量,以免违反封装原则(这在 OO 编程中非常重要)。

In the end it's a matter of choice, but you're saving one method call using your first example.最后,这是一个选择问题,但是您使用第一个示例保存了一个方法调用。

I think we should use getters() and setters() instead of accessing directly.我认为我们应该使用getters()setters()而不是直接访问。 It is also makes debugging very easy;这也使调试变得非常容易; for example, if you need to assign a variable to multiple place in your class and later want to find out from how many places the variable is assigned to, then you need to find all the assignment and set the break point.例如,如果您需要将一个变量分配到类中的多个位置,然后想从该变量分配到多少个位置中找出,那么您需要找到所有分配并设置断点。

However, if you use a setter you can simply put a break point inside the setter method and can see how many time the variable is assigned.但是,如果您使用 setter,您可以简单地在 setter 方法中放置一个断点,并可以查看变量被分配了多少次。

I use a mix of both.我使用两者的混合。 Accessor methods add more clutter so I use them only when the variable is used many times.访问器方法会增加更多的混乱,所以我只在多次使用变量时才使用它们。 If the variable is used only once or twice I don't use them.如果变量只使用一次或两次,我不使用它们。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM