Constants Class


#1

(I’m still learning the language, it’s just a couple of days ago I started). In Java land I generally write constants class in this fashion:

public final class ColumnLengths {
    public static final int EMAIL = 128;
    public static final int ENUM = 10;
    public static final int PRINCIPAL_LENGTH = 64;
    private ColumnLengths() {
    }
}

When I use the Kotlin converter I get:

object ColumnLengths {
    val EMAIL = 128
    val ENUM = 10
    val NAME = 256
    val PRINCIPAL_LENGTH = 64
}

My questions on the result are:

  • is this the most optimal way to represent a constants class in Kotlin?
  • does this prevent instantiation and inheritance (I had prevented it on Java by using a final class and private constructor)

Perhaps in terms of language design I am thinking we should have a more well defined construct for this since for me constant classes are a common pattern. However do not make them equivalent to utility classes that have executable methods. I was thinking of

val object ColumnLengths {
    EMAIL = 128
    ENUM = 10
    NAME = PRINCIPAL_LENGTH * 2
    PRINCIPAL_LENGTH = 64
}

The key thing I want to point out when it does the parsing is that it needs to resolve the order on its own. This is one of the flaws in Java in that if you “sort” the names and one needs the value of another constant below it will error out.

Since the above constant class is not open and can never be open it should as part of compilation step do a graph internally to ensure that the values are set in the right order and determine if there are any cycles in which case the compiler will error out.


#2

The ‘object’ keyword in Kotlin creates a singleton.

So it’s not possible to create any further instances of your ColumnLengths object. Nor is it possible to inherit from it.

Also ‘objects’ can’t have constructors and their properties are initialized in the order they are declared. If you need to do any more complicated initializations, then this can be done in an init{} block.

So, yes, I would say the Kotlin converter gives a reasonably optimal way to represent your constants class.

However, you could declare your properties as compile time constants by preceding them with the ‘const’ modifier as a further optimization here.


#3

Can you quickly show me where that is documented? That sounds like a very awesome feature.


#4

Sure, here are links to where compile-time constants and objects are discussed in the official documentation.


#5

Oh that was kind of disappointing… I was expecting something like Java .properties file and somehow we can do something like

import some.package.Constants

And Constants is named Constants.properties and looks like

Name.String=foo
Name.Integer=3

Then in our code we’d have

fun hello() {
    print(Constants.Name_String)
    print(Constants.Name_Integer + 5)
    print(Constants.Name_Integer.asString())
}

#6

That’s no problem:

package mypackage

object Constants {
    const val NAME_STRING = "foo"
    const val NAME_INTEGER = 3
}
  
fun hello() {
    println(Constants.NAME_STRING)
    println(Constants.NAME_INTEGER + 5)
    println(Constants.NAME_INTEGER.toString()) 
}

fun main(args: Array<String>) = hello()

#7

Yes I know it can be done as above, I was just hoping the tooling will allow the use of properties files as code rather than writing some more code.


#8

Also note that you don’t necessary have to namespace your constants, you can declare them as a top-level values without an additional wrapper object.


#9

I’m probably misunderstanding your issue, but why can’t you just use a properties file as you would normally with java?


#10

Because properties files still need to be referred to by strings in Java.
If it were converted to code at least for the keys so it can be used with
the IDE for auto completion and compile time checks rather than runtime.

I think c# has something akin to synthetic but for XAML rather than simple
properties.


#11

Ah, you want this for serialization! I think you would very much enjoy using Gson!


#12

Let try this again…

Let’s say I have a two properties files

com/movie/Resource.properties with

Page.Title=A new movie
Page.Description=Some other thing from the planet

com/movie/Resource_tl_PH.properties

Page.Title=Bagong Pilikula
Page.Description=Bagay sa ibang bansa

Let’s save I have some Java class

@Properties("com.movies.Resource")
public class MyClass {
   public int main(String[] argv) {
       System.out.println(Resource.PAGE_TITLE());
       Locale.setDefault(new Locale("tl", "PH");
       System.out.println(Resource.PAGE_TITLE());
   }
}

I would expect it to print out

A new movie
Bagong Pilikula

Resource would be a generated class using APT that would look something like

public final class Resource {
   private static ResourceBundle bundle = ResourceBundle.getBundle("com/movie/Resource");
   public static final String PAGE_TITLE(Object... args) { return String.format(bundle.get("Page.Title", args)); }
   ...
}

Of course with a bit of optimization when there there are no args and alternatives like using Message Bundle etc and supporting non string types.

I think the best way I want something like this is for “familiarity” most developers and even ops would know how a properties file is generally supposed to look like.


#13

I would never expect such a thing from the core language. It is relatively trivial to create build steps to generate source files (e.g. using a velocity template) or use an annotation processor to generate the code.