“特殊属性/属性”而不是Java中的getter / setter来避免锅炉板代码 [英] "Special attributes/properties" instead of getter/setter in Java to avoid boiler plate code

查看:133
本文介绍了“特殊属性/属性”而不是Java中的getter / setter来避免锅炉板代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

简介

我正在开发一个开源项目 Treez 我在树视图中组织所谓的Atoms。这些Atom有时具有很多属性,并且这些属性可以通过树视图中的用户操作或Eclipse代码编辑器中的 API 进行修改。

I am working on an open source project Treez where I organize so called "Atoms" in a tree view. Those Atoms sometimes have a lot of attributes and those attributes are modified either through user actions in a tree view or through an API in an Eclipse code editor.

我的Atoms本身的属性由可重用的AttributeAtoms表示。那些包含实际属性值并提供诸如验证之类的附加功能(Atom的其他可能术语可能是小部件,bean,属性或树节点)。

The attributes of my Atoms themselves are represented by reusable "AttributeAtoms". Those hold the actual attribute value and provide additional functionality like validation (other possible terms for "Atom" might be "widget", "bean", "property" or "tree node").

问题

过去我提供了一个getter / setter为我的每个Atom属性配对。这是一项额外的工作,它会夸大我的Atom类的大小(参见下面的代码示例)。现在我正在寻找一种替代解决方案

In the past I provided a getter/setter pair for each of my Atom attributes. This is a lot of extra work and it blows up the size of my Atom classes (see code examples below). Now I am looking for an alternative solution that


  • 使创建新Atoms的工作量减少(维护它们的工作量减少)。

  • 避免使用冗余的getter / setter锅炉板代码。

我将在下面介绍几个选项。你会使用哪个选项?您有关于如何改进这些选项的建议吗?你还知道更多的选择吗?

I'm going to describe a few options below. Which of the options would you use? Have you suggestions on how to improve those options? Do you know even further options?

Getter / Setter代码示例

    private AttributeAtom<String> myAttribute = new FilePathAttributeAtom("myAttribtue");

    public String getMyAttribute() {
        return myAttribute.getValue();
    }    

    public void setMyAttribute(String value) {
        this.myAtrribute.setValue(value);
    }

相关文章

  • does java have something similar to C# properties?
  • (no) Properties in Java?
  • http://blog.netopyr.com/2011/05/19/creating-javafx-properties/
  • http://www.eclipse.org/forums/index.php/t/781816/
  • Why use getters and setters?
  • What is the advantage of having a private attribute with getters and setters?

考虑选项

A.使用IDE自动生成getter / setter

Eclipse提供了自动生成getter / setter的可能性。

Eclipse provides the possibility to auto generate getters/setters.


  • 对于我的AttributeAtoms不起作用,因为gettter / setter代码看起来略有不同。

  • 不能避免额外的冗余代码。

如果我决定保留getter / setter,我可以尝试为AttributeAtoms创建类似的东西。另请参阅此文章关于(不工作)JavaFx属性的自动getter / setter创建:
http://www.eclipse.org/forums/index.php/t/781816/

If I decide to keep the getters/setters, I could try to create something similar for my AttributeAtoms. Also see this post about (not working) automatic getter/setter creation for JavaFx Properties: http://www.eclipse.org/forums/index.php/t/781816/

B.生成getter / setter的注释(Project Lombok)

Lombok提供了使用Annotations自动生成getter和setter的可能性。

Lombok provides the possibility to use Annotations for the automatic generation of getters and setters.


  • 对我的AttributeAtoms都不起作用

  • 我尝试将Lombok与Eclipse一起使用。编辑器中的代码完成工作但我得到了找不到方法的警告。我可能需要投入更多时间让Lombok为经典属性工作。

  • 另见使用Project Lombok是否安全?

  • Does neither work for my AttributeAtoms
  • I tried to use Lombok with Eclipse. The code completion in the editor worked but I got "method not found" warnings. I might need to invest some more time to get Lombok working for classical attributes.
  • Also see Is it safe to use Project Lombok?

如果我决定使用Annotations定义getter / setter,可以扩展Lombok以适用于我的AttributeAtoms。

If I decide to use Annotations to define getters/setters, it might be possible to extend Lombok to work for my AttributeAtoms.

这是一个介绍关于如何使用自定义转换扩展Lambok:
http ://notatube.blogspot.de/2010/12/project-lombok-creating-custom.html

Here is an intro on how to extend Lambok with custom transformations: http://notatube.blogspot.de/2010/12/project-lombok-creating-custom.html

<强>℃。一个用于所有属性的通用getter / setter

我可以为所有Atom属性使用单个getter / setter对,例如

I could use a single getter/setter pair for all Atom attributes like

Object get(String attributeName)
void set(String attriuteName, Object value)




  • 通过传递其他类型参数可以改善类型安全性。

  • 但是,我的Atom的代码完成只建议单个getter / setter,用户不会看到哪些属性可用。 (也许这可以通过使用Enums而不是字符串来识别属性。但是那些枚举需要以某种方式创建。另请参阅下一个选项。)

  • D.自定义Eclipse编辑器和代码处理

    也许我可以为我的开源项目编写一个额外的Eclipse插件允许访问私有属性,建议相应的假代码完成的方法。在编译用户源代码之前,虚假调用如

    Maybe I could write an extra Eclipse plugin for my open source project that "allows to access private attributes" by suggesting corresponding fake methods for the code completion. Before compiling the user source code, fake calls like

    myAtom.setMyAttribue(newValue);
    

    将被转换为真正存在的通用getter的代码(选项C):

    would be translated to code for the really existing generalized getter (option C):

    myAtom.set("myAttribute", newValue);
    

    E.公共属性

    如果我公开我的Atom属性,我不需要在每个Atom中使用getter / setter代码。相反,可重用的AttributeAtoms将提供get / set方法。用法例如如下所示

    If I make my Atom attributes public, I do not need getters/setter code in each Atom. Instead, the reusable AttributeAtoms would provide get/set methods. The usage would for example look like this

    myAtom.myAttribute.get();
    myAtom.myAttribute.set(newValue);
    

    而不是

    myAtom.getMyAttribute();
    myAtom.setMyAttribute(newValue);
    

    一些缺点:


    • 用户需要习惯这种非常规方法。 Java用户可能期望 setMyAttribute(newValue),而C#用户可能期望 myAtom.myAttribute = newValue

    • 可以交换整个AttributeAtom ,我不想允许

    • Users need to get used to this "unconventional approach". Java users might expect setMyAttribute(newValue) and C# users might expect myAtom.myAttribute = newValue.
    • It is possible to exchange the whole AttributeAtom, which I do not want to allow:

    myAtom.myAttribute = completelyDifferentAttribute
    


    任何改善这个的策略?


    • 有没有办法允许访问属性的方法,而不允许交换属性本身?我需要一个新的访问修饰符,如

    • Is there a way to allow the access to the methods of an attribute while not allowing to exchange the attribute itself? I would need a new access modifier like

    private *publicMethodAccess* AttributeAtom<String> myAttribute;
    


    Atom代码示例

    这是Atom类的示例。如果滚动到底部,您会发现getter / setter消耗的许多代码行。这很难看,不是吗?

    Here is an example Atom class. If you scroll to the bottom you will find many lines of code that are consumed by the getters/setters. This is ugly, isn't it?

    package org.treez.results.atom.probe;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import org.apache.log4j.Logger;
    import org.eclipse.swt.graphics.Image;
    import org.treez.core.atom.attribute.AttributeRoot;
    import org.treez.core.atom.attribute.ModelPath;
    import org.treez.core.atom.attribute.ModelPathSelectionType;
    import org.treez.core.atom.attribute.Section;
    import org.treez.core.atom.attribute.base.AttributeAtom;
    import org.treez.core.atom.variablerange.VariableRange;
    import org.treez.core.data.column.ColumnType;
    import org.treez.data.column.Columns;
    import org.treez.data.output.OutputAtom;
    import org.treez.data.table.Table;
    import org.treez.results.Activator;
    
    /**
     * Collects data from a sweep and puts it in a single (probe-) table. That table can easier be used to produce plots
     * than the distributed sweep results.
     */
    public class SweepProbe extends AbstractProbe {
    
        /**
         * Logger for this class
         */
        @SuppressWarnings("unused")
        private static Logger sysLog = Logger.getLogger(SweepProbe.class);
    
        //#region ATTRIBUTES
    
        private AttributeAtom<String> xLabel;
    
        private ModelPath xRange;
    
        private AttributeAtom<String> yLabel;
    
        private AttributeAtom<String> firstFamilyLabel;
    
        private ModelPath firstFamilyRange;
    
        private AttributeAtom<String> secondFamilyLabel;
    
        private ModelPath secondFamilyRange;
    
        private AttributeAtom<String> probeName;
    
        private ModelPath sweepOutputModel;
    
        private ModelPath firstProbeTable;
    
        private AttributeAtom<String> probeColumnIndex;
    
        private AttributeAtom<String> probeRowIndex;
    
        //#end region
    
        //#region CONSTRUCTORS
    
        /**
         * Constructor
         *
         * @param name
         */
        public SweepProbe(String name) {
            super(name);
            createPropertyModel();
        }
    
        //#end region
    
        //#region METHODS
    
        /**
         * Creates the model for the property control
         */
        private void createPropertyModel() {
    
            //root
            AttributeRoot root = new AttributeRoot("root");
    
            //page
            org.treez.core.atom.attribute.Page page = root.createPage("page");
    
            //x section
            Section xSection = page.createSection("xSection", "X");
            xSection.createSectionAction("action", "Run probe", () -> execute(treeViewRefreshable));
    
            xLabel = xSection.createTextField("xLabel", "Label for x-Axis", "x");
    
            xRange = xSection.createModelPath("xRange", "Range for x-Axis", "", VariableRange.class, this);
            xRange.setSelectionType(ModelPathSelectionType.FLAT);
            xRange.setValue("root.studies.sweep.threshold");
    
            //y section
            Section ySection = page.createSection("ySection", "Y");
            yLabel = ySection.createTextField("yLabel", "Label for y-Axis", "y");
    
            //first family section
            Section firstFamilySection = page.createSection("firstFamily", "First family");
            firstFamilySection.setExpanded(false);
    
            firstFamilyLabel = firstFamilySection.createTextField("firstFamilyLabel", "Label for first family", "family1");
    
            firstFamilyRange = firstFamilySection.createModelPath("firstFamilyRange", "Range for first family", "",
                    VariableRange.class, this);
    
            //second family section
            Section secondFamilySection = page.createSection("secondFamily", "Second family");
            secondFamilySection.setExpanded(false);
    
            secondFamilyLabel = secondFamilySection.createTextField("secondFamilyLabel", "Label for second family",
                    "family2");
    
            secondFamilyRange = secondFamilySection.createModelPath("secondFamilyRange", "Range for second family", "",
                    VariableRange.class, this);
    
            //probe section
            Section probeSection = page.createSection("probe", "Probe");
    
            probeName = probeSection.createTextField("propeName", "Name", "MyProbe");
    
            sweepOutputModel = probeSection.createModelPath("sweepOutput", "SweepOutput", "", OutputAtom.class, this);
    
            firstProbeTable = probeSection.createModelPath("tablePath", sweepOutputModel, Table.class);
            firstProbeTable.setLabel("First probe table");
    
            probeColumnIndex = probeSection.createTextField("probeColumnIndex", "Column index", "0");
    
            probeRowIndex = probeSection.createTextField("probeColumnIndex", "Row index", "0");
    
            setModel(root);
    
        }
    
        /**
         * Provides an image to represent this atom
         */
        @Override
        public Image provideBaseImage() {
            Image baseImage = Activator.getImage("sweep.png");
            return baseImage;
        }
    
        //#region CREATE TABLE COLUMNS
    
        /**
         * Creates the required columns for the given table
         *
         * @param table
         */
        @Override
        protected void createTableColumns(Table table) {
            //TODO
    
        }
    
        //#end region
    
        //#region COLLECT PROBE DATA
    
        @Override
        protected void collectProbeDataAndFillTable() {
            // TODO Auto-generated method stub
    
        }
    
        //#end region
    
        //#end region
    
        //#region ACCESSORS
    
        //#region X LABEL
    
        /**
         * @return
         */
        public String getXLabel() {
            return xLabel.getValue();
        }
    
        /**
         * @param label
         */
        public void setXLabel(String label) {
            xLabel.setValue(label);
        }
    
        //#end region
    
        //#region X RANGE
    
        /**
         * @return
         */
        public String getXRange() {
            return xRange.getValue();
        }
    
        /**
         * @param range
         */
        public void setXRange(String range) {
            xRange.setValue(range);
        }
    
        //#end region
    
        //#region Y LABEL
    
        /**
         * @return
         */
        public String getYLabel() {
            return yLabel.getValue();
        }
    
        /**
         * @param label
         */
        public void setYLabel(String label) {
            yLabel.setValue(label);
        }
    
        //#end region
    
        //#region FIRST FAMILY LABEL
    
        /**
         * @return
         */
        public String getFirstFamilyLabel() {
            return firstFamilyLabel.getValue();
        }
    
        /**
         * @param label
         */
        public void setFirstFamilyLabel(String label) {
            firstFamilyLabel.setValue(label);
        }
    
        //#end region
    
        //#region FIRST FAMILY RANGE
    
        /**
         * @return
         */
        public String getFirstFamilyRange() {
            return firstFamilyRange.getValue();
        }
    
        /**
         * @param range
         */
        public void setFirstFamilyRange(String range) {
            firstFamilyRange.setValue(range);
        }
    
        //#end region
    
        //#region SECOND FAMILY LABEL
    
        /**
         * @return
         */
        public String getSecondFamilyLabel() {
            return secondFamilyLabel.getValue();
        }
    
        /**
         * @param label
         */
        public void setSecondFamilyLabel(String label) {
            secondFamilyLabel.setValue(label);
        }
    
        //#end region
    
        //#region SECOND  FAMILY RANGE
    
        /**
         * @return
         */
        public String getSecondFamilyRange() {
            return secondFamilyRange.getValue();
        }
    
        /**
         * @param range
         */
        public void setSecondFamilyRange(String range) {
            secondFamilyRange.setValue(range);
        }
    
        //#end region
    
        //#region PROBE
    
        /**
         * @return
         */
        public String getProbeName() {
            return probeName.getValue();
        }
    
        /**
         * @param name
         */
        public void setProbeName(String name) {
            probeName.setValue(name);
        }
    
        //#end region
    
        //#region SWEEP OUTPUT MODEL
    
        /**
         * @return
         */
        public String getSweepOutputModelName() {
            return sweepOutputModel.getValue();
        }
    
        /**
         * @param sweepOutputModel
         */
        public void setSweepOutputModelName(String sweepOutputModel) {
            this.sweepOutputModel.setValue(sweepOutputModel);
        }
    
        //#end region
    
        //#region PROBE TABLE
    
        /**
         * @return
         */
        public String getFirstProbeTable() {
            return firstProbeTable.getValue();
        }
    
        /**
         * @param firstProbeTable
         */
        public void setFirstProbeTable(String firstProbeTable) {
            this.firstProbeTable.setValue(firstProbeTable);
        }
    
        //#end region
    
        //#region COLUMN INDEX
    
        /**
         * @return
         */
        public String getProbeColumnIndex() {
            return probeColumnIndex.getValue();
        }
    
        /**
         * @param index
         */
        public void setProbeColumnIndex(String index) {
            probeColumnIndex.setValue(index);
        }
    
        //#end region
    
        //#region ROW INDEX
    
        /**
         * @return
         */
        public String getProbeRowIndex() {
            return probeRowIndex.getValue();
        }
    
        /**
         * @param index
         */
        public void setProbeRowIndex(String index) {
            probeRowIndex.setValue(index);
        }
    
        //#end region
    
        //#end region
    
    }
    


    推荐答案

    对于选项E,通过使用final修饰符,可以防止交换全新的AttributeAtom ,同时仍然允许获取/设置:

    For Option E, by using the "final" modifier you could prevent a whole new AttributeAtom being swapped in, whilst still allowing getting/setting:

    public final AttributeAtom<String> myAttribute = new FilePathAttributeAtom("myAttribtue");
    

    然后将允许以下内容:

    myAtom.myAttribute.get();
    myAtom.myAttribute.set(newValue)
    

    但你担心的事情赢了不是:

    But the thing you're worried about won't be:

    myAtom.myAttribute = completelyDifferentAttribute
    

    这篇关于“特殊属性/属性”而不是Java中的getter / setter来避免锅炉板代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆