简体   繁体   English

在其getter中调用数据成员的setter

[英]Calling a data member's setter in its getter

This question is kind of linked to this other question I asked in this forum. 这个问题有点类似于我在这个论坛上问的另一个问题

Here is what I am trying to accomplish. 这是我要完成的工作。 I have the following class: 我有以下课程:

public class LoginPage
{
    // Class Data
    private HtmlForm loginForm;

    // Calling the constructor of the parent class
    public LoginPage()
    {
        loginForm = null;
    }

    public void setLoginForm()
    {
        ...... logic to find the login form ........
    }

    public HtmlForm getLoginForm()
    {
        return loginForm;
    }

    ...... other login related methods ........
}

I want to ensure that every time a getLoginForm() method is called it should not return null. 我想确保每次调用getLoginForm()方法时都不应返回null。 One way to do this is to ensure setLoginForm() is called before the getLoginForm() method is called. 一种方法是确保在调用getLoginForm()方法之前调用setLoginForm()。

Can i call the setter of a data member within its getter method. 我可以在其getter方法中调用数据成员的setter吗? In this case: 在这种情况下:

    public HtmlForm getLoginForm()
    {
        setLoginForm()
        return loginForm;
    }

I have never seen some thing like this being practiced. 我从未见过像这样的事情正在被实践。 Is this valid ? 这有效吗? What are the merits and demerits of doing this ? 这样做的优点和缺点是什么?

Appreciate your comments / suggestions !!!! 感谢您的意见/建议!

The usual pattern for this would be something like: 通常的模式如下:

public class LoginPage {

    // Class Data
    private HtmlForm loginForm;

    // Calling the constructor of the parent class
    public LoginPage() {
        loginForm = null;
    }

    // Normal setter - NB: Private - so I am in complete control.
    private void setLoginForm(HtmlForm loginForm) {
        this.loginForm = loginForm;
    }

    private void initialiseLoginForm() {
        if ( loginForm == null ) {
            // Build a loginForm and use the private setter to set it.
            // NB: In a multi-threaded environment you would normally use some kind of synchronization.
            HtmlForm newForm;
            // ...
            setLoginForm(newForm);
        }
    }

    // Normal getter
    public HtmlForm getLoginForm() {
        initialiseLoginForm();
        return loginForm;
    }

}

This creates the form late and disallows users from modifying it. 这会延迟创建表单,并禁止用户对其进行修改。 Note that I have used the correct signature for a setter which is usually setXxx(T it) . 请注意,我为setter使用了正确的签名,通常是setXxx(T it)

Is it "valid"? 是否有效? Sure. 当然。

Is it a good idea? 这是个好主意吗? Hard to say–depends on the situation. 很难说-取决于情况。

It's basically a "lazy" getter; 基本上,这是一个“懒惰”的吸气剂。 if the object hasn't been initialized, make sure it is, then return it. 如果对象尚未初始化,请确保已初始化,然后将其返回。

Unrelated but I'd argue the method is mis-named and should instead reflect something closer to what it's doing, eg, initLoginForm , findLoginForm , etc. 无关,但我认为该方法的名称不正确,应该反映出更接近其功能的内容,例如initLoginFormfindLoginForm等。

Technically it is valid, and as far as if it's useful, it depends on the situation... it could be useful to save some memory resources but you should make a small yet possibly very efficient change... (see bellow) 从技术上讲,它是有效的,并且它是否有用,取决于情况……节省一些内存资源可能很有用,但是您应该做一个很小但可能非常有效的更改……(请参见下面的内容)

I want to ensure that every time a getLoginForm() method is called it should not return null. 我想确保每次调用getLoginForm()方法时都不应返回null。

First of all, you should probably rename the setLoginForm() method to something like initLoginForm() . 首先,您可能应该将setLoginForm()方法重命名为initLoginForm() The reason is that setLoginForm() isn't really a setter and it serves to initialize the resources of the login form. 原因是setLoginForm()实际上不是设置方法,它用于初始化登录表单的资源。

A setter would look like this: 设置员看起来像这样:

    public void setLoginForm(HtmlForm loginForm) {
       this.loginForm = loginForm; // set the login form
    }

Right now, the way you have it is you call setLoginForm() each time you call getLoginForm() which is unnecessary. 现在,你有它的方式就是你所谓setLoginForm()每次调用getLoginForm()这是不必要的。 What you want is to instantiate the LoginForm only if it is null before returning it (this is called lazy initialization ). 您想要的是在返回LoginForm之前将其初始化 null ,以实例化LoginForm (这称为延迟初始化 )。

Lazy initializations means that we don't create objects until the first time we need them. 延迟初始化意味着我们直到第一次需要它们时才创建对象。 It is useful memory conservation technique because it refrains from creating certain resources until the resource is first needed -- freeing valuable memory space. 它是有用的内存保留技术,因为它避免了创建某些资源直到首次需要该资源时,从而释放了宝贵的内存空间。 It is especially useful when object initialization is expensive. 当对象初始化非常昂贵时,它特别有用。

So you make your getter be "lazy": 因此,您可以使自己的getter变得“懒惰”:

    public HtmlForm getLoginForm() {
        if(loginForm == null) { //first call to this method.
            loginForm = new HtmlForm();
        }
        return loginForm;
    }

The == null check should be the changed to however in your system design you would check " Is loginForm instantiated ". == null检查应该更改为,但是在您的系统设计中,您将检查“ Is LoginForm已实例化 ”。

I guess more general, your code could look like: 我想更一般地说,您的代码可能如下所示:

    public HtmlForm getLoginForm() {
        if(!isLoginFormInitialized()) { //initialize the login form if it isn't initialized
            initLoginForm();
        }
        return loginForm;
    }

This way you are still making sure your loginForm is initialized but you are not wasting resources by recreating it each time. 这样,您仍然可以确保您的loginForm已初始化,但不会通过每次重新创建来浪费资源。

NOTE: Since you didn't provide any specifications of your underlying system and how you setup the login form, do you allow null values, what design patterns you might be using etc. I just provided a general answer to what seems like you are asking. 注意:由于您没有提供有关基础系统的任何规范以及如何设置登录表单,因此您是否允许null值,您可能使用的设计模式等。我只是对您所询问的内容提供了一个一般性的答案。 。 Hopefully it helps :) 希望它会有所帮助:)

sure you could do it, but its not a goog idea. 确定您可以做到,但这绝不是好主意。

in general, a nice Application would be designed under the MVC Concept: 通常,将在MVC概念下设计一个不错的应用程序:

MVC: Model-View-Controller MVC:模型-视图-控制器

Model : your Objects like User(attributes and Getter + Setter), Product, Category,...etc. 模型 :您的对象,例如用户(属性和Getter + Setter),产品,类别等。 getter and Setters shouldn't have any Logic, just setting or getting values. getter和Setters不应具有任何逻辑,而只能设置或获取值。

View : your GUI 查看 :您的GUI

Controller : ManagedBeans that do logics, calculating, DataBase, ....etc. 控制器 :执行逻辑,计算,数据库等的ManagedBean。

if you want to check AND / OR init any values, then do this in the Controller not in the Model! 如果要检查AND / OR初始化任何值,请在Controller中而不是在Model中执行!

Usually, a setter Method needs a paramater to set the value: 通常,setter方法需要使用参数来设置值:

public void setData(DataType data ){
   this.data = data;
}

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

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