Home > database >  Kotlin constructor val vs private val
Kotlin constructor val vs private val

Time:07-24

If I have something like the following:

interface IRecordService {

   fun doSomething () : Record

}

@MongoRepository
interface IRecordRepository : MongoRepository<Record, String> {

}

@Service
class RecordService  (
   private val recordRepository : IRecordRepository // or just val instead of private val
) : IRecordService
{

   override fun doSomething () : Record {
      // does something
   }

}

Is there any difference between using private val in the RecordService constructor vs just val? I've seen both being used but couldn't tell if there was a recommended way or why.

CodePudding user response:

If you put val, it will be a constructor parameter and property. If you don't, it will be a constructor parameter (NOT property). See Why to put val or var in kotlin class constructors

CodePudding user response:

This isn't specific to Spring or Mongo; it's just core Kotlin. There are several things going on here; I'll try to unpick them.

Consider the simpler definition:

class MyClass(i: Int)

The parens specify the primary constructor: any parameters there (such as i) are passed into the class, and are available during construction. So you could pass them up to the superclass constructor, use them in property initialisers, and/or in an init block:

class MyClass(i: Int) : MySuperclass(i) {
    val someProperty = i

    init {
        println("i is $i")
    }
}

However, they don't persist after the instance has been constructed — so you couldn't refer to them in methods, or from outside the class.

If you want to do that, you have to define a property for each parameter you want to persist. You could do that explicitly, e.g.:

class MyClass(i: Int) {
    val i2 = i
}

Here every instance of MyClass has a property called i2 which is initialised to the i constructor parameter.

However, because this is a common pattern, Kotlin provides a shortcut. If you specify val or var in the primary constructor:

class MyClass(val i: Int)

then Kotlin creates a property with the same name as the parameter, and initialises it for you. So every instance of the above class has a property called i that you can refer to at any time.

By default, properties in Kotlin are public: you can access them from inside the class, from subclasses, from other classes in the same module, and from any other code that has a MyClass instance.

However, in some cases it's useful to restrict access, so you can add a visibility modifier: internal prevents code in other modules from seeing it, protected allows only subclasses to see it, and private makes it visible only inside the class itself.

So, to answer your question: without the private modifier, any code that had access to your RecordService would be able to access its recordRepository property; adding private prevents that, and means that only code within RecordService can see it.

In general, it might be a good idea to centralise all access to the recordRepository in the one class; then making it private would ensure that no other code can muck around with it. That would make it easier to see what's going on, easier to debug, and safer to work on. (However, we obviously don't know about the rest of your program, and can't advise on whether that would be a good plan in your case.)


By the way, using an I prefix for interfaces is not a convention that's used much in Kotlin (or Java). There's often little point in having an interface with only one implementation; and if you could have multiple implementations, then better to use a simple term for the interface and then more specific terms for the implementations.  (For example: the List interface with ArrayList and LinkedList classes, or Number with Int and Long.)

CodePudding user response:

Firstly if you use val it converts this constructor parameter to property,If you do not want to hide this property (to set it) from other classes,you can use val.But if you do not want your property to be changed by other classes you should use private val instead.

CodePudding user response:

Well, you can use both val and private val in your constructor there's no problem in that, it's just that with private keyword your properties wont be modified or accessed by some other class, so it basically provides some data hiding. If you talking about difference in functionality inside your RecordService class, then no there wont be any difference.

  • Related