Can you use a concept similar to keyword args for python in Java to minimize the number of accessor methods?
Asked Answered
B

4

11

I recently learn that in Python 3, to minimize the number of accessor methods for a class, you can use a dictionaries to essentially just have one set of accessor methods as follows:

def __init__(self, **kwargs):
    self.properties = kwargs

def get_properties(self):
    return self.properties

def get_property(self, key):
    return self.properties.get(key, None)

This seems really useful and I want to apply something similar in Java. I have been working on applications that may have multiple attributes, and creating and keeping track of all the accessor methods can be a pain. Is there a similar strategy that I could use for Java?

Bulb answered 28/4, 2015 at 0:6 Comment(1)
You could just use Python. •duck• :)Harmonist
A
5

Use that pattern if it suits and it fits best but it really should be an exception to the rule in Java - it will probably not be appropriate.

Best practice in Java is to use getter and setter methods for each variable. Yes it's more code - so what - if your lazy get your IDE to auto-generate them. It's there for a very good reason. Many good reasons. Some are;

  • Promotes private variables
  • Defines an external interface to other classes allowing the class to control what and how to set or get variables
  • Promotes good coding practice by establishing a standard way to deal with object variables

The problem you'll encounter here by porting this pattern over is due to typing. Python is dynamically typed and Java is statically typed. So, in order to use the same pattern in Java, you will have to store the values in something like a string/object array and then return them like that as an object or as a String. then you'll have to convert them sometime later. Maybe if your 'properties' were all strings it would be okay. There are exceptions to the rule, but you need to know all of the rules in order to break them well. If they are different types (String, int, CustomObject etc.) don't use the same pattern you use in Python.

Augustaugusta answered 28/4, 2015 at 0:26 Comment(3)
"but it really should be an exception to the rule in Java - it will probably not be appropriate." But that's not saying why, in principle? In practice, as you note, it's because Java's static typing won't allow it. But in principle it would be a good thing if the language could handle it. IDEs that autogenerate pages of accessors are a crutch, and make for flabby unreadable code. Not a feature.Frodine
Downvoted. IDE can write but can't read for you. Good reasons aren't really reasons: 1. Promotes private variables - isn't a value itself. What's the purpose? 2. External interfaces defined with the 'interface' keyword. If you need one - go and create it. Throwing more words in codebase and pretend that's an interface won't bring you anywhere. 3. So any other alternatives do.Ohare
Too much private vars with getters and setters promotes mutable state. Instead return a new object that you can use perhaps.Loreeloreen
C
7

No there is no kwargs in java. Instead you can something similar to your function by using java varargs to save them as java properties.

You do you can something like this:

useKwargs("param1=value1","param2=value2");

Example code:

public void useKwargs(String... parameters) {

        Properties properties = new Properties();

        for (String param : parameters) {
            String[] pair = parseKeyValue(param);

            if (pair != null) {
                properties.setProperty(pair[0], pair[1]);
            }

        }

        doSomething(properties);
    }

    public void doSomething(Properties properties) {
        /**
         * Do something using using parameters specified in the properties
         */

    }

    private static String[] parseKeyValue(String token) {
        if (token == null || token.equals("")) {
            return null;
        }

        token = token.trim();

        int index = token.indexOf("=");

        if (index == -1) {
            return new String[] { token.trim(), "" };
        } else {
            return new String[] { token.substring(0, index).trim(),
                    token.substring(index + 1).trim() };
        }

    }
Corabelle answered 26/6, 2017 at 9:36 Comment(0)
A
5

Use that pattern if it suits and it fits best but it really should be an exception to the rule in Java - it will probably not be appropriate.

Best practice in Java is to use getter and setter methods for each variable. Yes it's more code - so what - if your lazy get your IDE to auto-generate them. It's there for a very good reason. Many good reasons. Some are;

  • Promotes private variables
  • Defines an external interface to other classes allowing the class to control what and how to set or get variables
  • Promotes good coding practice by establishing a standard way to deal with object variables

The problem you'll encounter here by porting this pattern over is due to typing. Python is dynamically typed and Java is statically typed. So, in order to use the same pattern in Java, you will have to store the values in something like a string/object array and then return them like that as an object or as a String. then you'll have to convert them sometime later. Maybe if your 'properties' were all strings it would be okay. There are exceptions to the rule, but you need to know all of the rules in order to break them well. If they are different types (String, int, CustomObject etc.) don't use the same pattern you use in Python.

Augustaugusta answered 28/4, 2015 at 0:26 Comment(3)
"but it really should be an exception to the rule in Java - it will probably not be appropriate." But that's not saying why, in principle? In practice, as you note, it's because Java's static typing won't allow it. But in principle it would be a good thing if the language could handle it. IDEs that autogenerate pages of accessors are a crutch, and make for flabby unreadable code. Not a feature.Frodine
Downvoted. IDE can write but can't read for you. Good reasons aren't really reasons: 1. Promotes private variables - isn't a value itself. What's the purpose? 2. External interfaces defined with the 'interface' keyword. If you need one - go and create it. Throwing more words in codebase and pretend that's an interface won't bring you anywhere. 3. So any other alternatives do.Ohare
Too much private vars with getters and setters promotes mutable state. Instead return a new object that you can use perhaps.Loreeloreen
S
1

Im not sure if this is helpful to you, but Ill try to answer anyway. I'd first make a class Variable. Then I'd make a class Dictionary with one lists:Variables. Then I'd make the function take a Dictionary as argument.

Stokes answered 1/4, 2017 at 16:7 Comment(0)
K
1

kwargs are a dictionary, so you can use dictionary's analogue from java: maps. For example:

public class MyClass{
    HashMap<String, Object> params;

    // constructor for MyClass
    public MyClass(HashMap<String, Object> params){
        this.params = params;
    }
}

Another option is to have an additional class MyClassBuilder:

public class MyClassBuilder {

    private int param1 = default1;
    private String param2 = default2;
    private double param3 = default3;
    
    public MyClassBuilder(){
        // nothing to do here
    }
    
    public MyClassBuilder setParam1(int x){
        param1 = x;
        return this;
    }
    
    public MyClassBuilder setParam2(String x){
        param2 = x;
        return this;
    }
    
    public MyClassBuilder setParam3(double x){
        param1 = x;
        return this;
    }
       
    public MyClass build(){
        return new MyClass(param1, param2, param3);
    }

}

In the second case, you have do define a constructor for MyClass that takes three arguments (public MyClass(int p1, String p2, double p3))

In your main code, you can then write

MyClassBuilder mcb = new MyClassBuilder();
MyClass mc = mcb.setParam3(3.14).setParam2("foo").build();
Kathrinkathrine answered 4/4, 2022 at 11:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.