本站消息

站长简介/公众号


站长简介:高级软件工程师,曾在阿里云,每日优鲜从事全栈开发工作,利用周末时间开发出本站,欢迎关注我的微信公众号:程序员总部,程序员的家,探索程序员的人生之路!分享IT最新技术,关注行业最新动向,让你永不落伍。了解同行们的工资,生活工作中的酸甜苦辣,谋求程序员的最终出路!

  价值13000svip视频教程,java大神匠心打造,零基础java开发工程师视频教程全套,基础+进阶+项目实战,包含课件和源码

  出租广告位,需要合作请联系站长


+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

暂无数据

“特殊属性/属性”而不是 Java 中的 getter/setter 以避免样板代码

发布于2021-11-28 10:30     阅读(158)     评论(0)     点赞(23)     收藏(4)


介绍

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

我的 Atom 本身的属性由可重用的 "AttributeAtoms" 表示那些持有实际的属性值并提供额外的功能,如验证(“Atom”的其他可能术语可能是“widget”、“bean”、“property”或“树节点”)。

问题)

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

  • 使创建新 Atom 的工作更少(维护它们的工作更少)。
  • 避免“冗余”的 getter/setter 样板代码。

我将在下面描述几个选项。您会使用哪些选项?您对如何改进这些选项有什么建议吗?你知道更多的选择吗?

Getter/Setter 代码示例

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

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

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

相关文章

考虑的选项

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

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

  • 不适用于我的 AttributeAtoms,因为 getter/setter 代码看起来略有不同。
  • 不避免额外的“冗余”代码。

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

B. 生成 getter/setter 的注解(龙目岛项目)

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

  • 对我的 AttributeAtoms 都不起作用
  • 我尝试在 Eclipse 中使用 Lombok。编辑器中的代码完成工作,但我收到“方法未找到”警告。我可能需要投入更多时间让 Lombok 为经典属性工作。
  • 另请参阅使用 Project Lombok 是否安全?

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

  • 此处已存在为 JavaFx 属性扩展 Lombok 的请求:https ://groups.google.com/forum/#!searchin/project-lombok/getter$20and$20setter$20for$20properties/project-lombok/Ik6phxDXHVU/zzDkC2MpmvgJ

  • 以下是有关如何使用自定义转换扩展 Lambok 的介绍:http ://notatube.blogspot.de/2010/12/project-lombok-creating-custom.html

C. 一个适用于所有属性的通用 getter/setter

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

Object get(String attributeName)
void set(String attriuteName, Object value)
  • 可以通过传递额外的类型参数来提高类型安全性。
  • 但是,我的 Atom 的代码完成只会建议单个 getter/setter,用户不会看到哪些属性可用。(也许这可以通过使用枚举而不是字符串来标识属性来解决。但这些枚举需要以某种方式创建。另见下一个选项。)

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

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

myAtom.setMyAttribue(newValue);

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

myAtom.set("myAttribute", newValue);

E. 公共属性

如果我公开我的 Atom 属性,我不需要每个 Atom 中的 getter/setter 代码。相反,可重用的 AttributeAtom 将提供 get/set 方法。例如,用法看起来像这样

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

代替

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

一些缺点:

  • 用户需要习惯这种“非常规方法”。Java 用户可能期望setMyAttribute(newValue),C# 用户可能期望myAtom.myAttribute = newValue.
  • 可以交换整个 AttributeAtom,这是我不想允许的

    myAtom.myAttribute = completelyDifferentAttribute
    

有什么策略可以改善这一点吗?

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

    private *publicMethodAccess* AttributeAtom<String> myAttribute;
    

原子代码示例

这是一个示例 Atom 类。如果滚动到底部,您会发现 getter/setter 使用的许多代码行。这很丑,不是吗?

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

}

解决方案


Some years later I want to add that I entirely switched to JavaScript. That seems to be the better language for my use case.



所属网站分类: 技术文章 > 问答

作者:黑洞官方问答小能手

链接:http://www.javaheidong.com/blog/article/337850/4710d91cb89e45a0685c/

来源:java黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

23 0
收藏该文
已收藏

评论内容:(最多支持255个字符)