https://kotlinlang.org logo
b

Ben Edwards

09/16/2022, 8:53 AM
Trying to get my head around what internal means. Been doing a bit of reading (https://kotlinlang.org/docs/visibility-modifiers.html, https://kotlinlang.org/spec/packages-and-imports.html#modules, https://www.digitalocean.com/community/tutorials/kotlin-visibility-modifiers-public-protected-internal-private). The digitalocean.com seems to sum it all up and is consistent with the kotlinlang.org docs. Come with me down the rabbit hole :). I understand everything here apart from internal and exactly what a module is. It says "Setting a declaration as internal means that it’ll be available in the same module only. By module in Kotlin, we mean a group of files that are compiled together.". I think the sticking point for me is "Compiled together". What exactly does that mean? Is this something to do with packages? Or is it simply referring to the current .kt file? The other thing that got me wondering is the use of
Copy code
private const val TAG = "BaseActivity"
Which can put just after the imports. Its not defined within a class which seems inconsistent with private being '`private` means that the member is visible inside this class only (including all its members).'. Does it effectively become private to all classes in the file? To go further down the rabbit hole what does 'including all its members' mean? I guess it means function/methods but if so why not just say this?
👌 1
y

Youssef Shoaib [MOD]

09/16/2022, 9:01 AM
A module is basically the same as a gradle module. Meaning that basically all files inside /src/main and /src/test are considered part of the same module. Adding more modules is trivial and can be done inside IntelliJ idea using File -> New -> new module
j

Joffrey

09/16/2022, 9:03 AM
"compiled together" is meant literally: passed to the compiler together. When you run the compiler, you don't compile one file at a time. You pass a set of source files that are read and compiled all together at the same time, and usually this produces a set of classes that are packed in a single jar file. Compiling files together allows code from a file to reference declarations from a different file without having to declare any dependency relationship between these files. The files compiled together constitute a module. When you use declarations from a module in another module, you have to declare that dependency somehow. If you call the compiler by hand, you would have to pass extra arguments to point the compiler to the required dependencies so it can compile the files that use stuff from other modules.
internal
is a visibility modifier that forbids access from other modules. The declaration can only be accessed by the files that are compiled at the same time as the file declaring the
internal
declaration
Its not defined within a class which seems inconsistent with private being '`private` means that the member is visible inside this class only (including all its members).'. Does it effectively become private to all classes in the file?
private
at the top-level means private in the file. The declaration can be used anywhere in the file (including inside classes declared in that file), but not outside the file. Technically talking about a class is not wrong, because top-level declarations in Kotlin are actually compiled as if they were part of a class. If you have a file called
MyFile.kt
, Kotlin will generate a class called
MyFileKt
to hold all the top-level declarations from that file. That said,
private
at the top level doesn't mean private in that generated class, because other classes in the same file can use those top-level declarations.
To go further down the rabbit hole what does 'including all its members' mean? I guess it means function/methods but if so why not just say this?
"member" is a specific term that refers to many things a class can hold. It's just the correct vocabulary to use, and it would be quite verbose to cite them all every time. See https://kotlinlang.org/docs/classes.html#class-members In this specific instance, it means that a private thing in a class can still be visible to the body of the classe's methods and constructors, to property initializers, to
init
blocks, and can also be accessed in nested classes and objects, etc.
b

Ben Edwards

09/16/2022, 9:13 AM
@Joffrey (re private) thanks, that is great to know, makes sense. Shame docs don't say that. So if the private was declared inside a class in the file exactly what does that mean? Can other classes inside the file that have instances of the class with the private member access that member?
j

Joffrey

09/16/2022, 9:17 AM
Can other classes inside the file that have instances of the class with the private member access that member?
Nope. Private visibility on a declaration at the top-level in a file means that everything else in the file can see it, but private visibility on a class member means that only other members in the same class can see it. Holding an instance of that class from anywhere outside the class only gives you access to the API of the class that have sufficient visibility (internal, public, protected depending on where you are). I hope that makes it clearer. EDIT: here is a quick rule of thumb: if you see
private
, it means the declaration is visible only to things that are in the enclosing block
{ ... }
and everything nested in it. If there is no enclosing block, consider the whole file. (Note that I haven't thought this rule through, so maybe there are exceptions, but I find it quite neat to help grasp the idea quickly)
👃 1
👍 1
b

Ben Edwards

09/16/2022, 9:21 AM
@Joffrey (re internal) ime doing Android Dev in Android Studio. So is a module everything in the project (I guess IntelliJ is the same) unless you specifically create multiple modules. Trying to get my head around when I should use internal, and I guess why? Maybe in my relatively early stage in my learning, I should park this one, feels above my paygrade at the moment😀
@Joffrey think we need to turn the kotlinland.org docs into a wiki or at least have a feedback/suggestion method!
j

Joffrey

09/16/2022, 9:33 AM
So is a module everything in the project (I guess IntelliJ is the same) unless you specifically create multiple modules
I haven't done Android dev in a very long time, but AFAIK now you have a sort of a top-level Gradle module, and then a nested
app
module. But yeah pretty much everything you'll be interested in will be in that single app module, unless you create other modules yourself.
Trying to get my head around when I should use internal, and I guess why? Maybe in my relatively early stage in my learning, I should park this one
Everything
internal
in your app module will indeed be visible in the whole module anyway, so yeah
internal
isn't useful when developing in a single-module project. Creating more modules is often useful for libraries that want to publish separate "things" that can be used independently (the library is thus "modular"). Even in a single project where you build only one thing, it was also useful in the past to split it into multiple modules to benefit for incremental compilation, but now I believe Kotlin supports incremental compilation within single modules too. Modules can only be useful on their own exactly for the purpose of isolating things visibility-wise, making use of internal (because Kotlin doesn't have package-private visibility).
b

Ben Edwards

09/16/2022, 9:44 AM
@Joffrey yes, I figured that was the case. I think the tutorial used internal as a learning thing but probably should not have bothered as don't think it was necessarily appropriate and did not take the time to properly explain it. It said internal meant only available in the project, which is true but a gross over-simplification. When learning I generally need to fully understand everything to move on. The code was actually.
Copy code
package com.funkytwig.flickerbrowser

import android.util.Log
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar

private const val TAG = "BaseActivity"

// internal as don't have to be available outside this project 
internal const val FLICKER_QUERY = "FLICKER_QUERY"
internal const val PHOTO_TRANSFUR = "PHOTO_TRANSFUR"

open class BaseActivity : AppCompatActivity() {
    internal fun activateToolbar(home: Boolean) {
        Log.d(TAG, "activateToolbar")

        val toolbar = findViewById<View>(R.id.toolbar) as Toolbar
        setSupportActionBar(toolbar)
        supportActionBar?.setDisplayHomeAsUpEnabled(true) // Set whether home should be displayed as an "up" affordance.
    }
}
I guess there is not a benefit of using internal here (drought the course even covers modules, or if it does will be a long way down the road). Thanks for being very generous with your time.
j

Joffrey

09/16/2022, 9:53 AM
Yes it's likely a bit early to introduce
internal
visibility, but I don't know the tutorial so I'm not sure what path they want their readers to follow
Thanks for being very generous with your time
My pleasure!
6 Views