Lombok has a neat feature to use var instead of local variable datatype declarations. Is there a way to "refactor" your entire code base automatically to use var whenever applicable? I'm using IntelliJ IDEA and the Lombok plugin. I didn't find a feature like this.
Also, does it even make sense since var is still considered "experimental" so it might "mess up" the code base when it gets deprecated/is somehow bugged/gets replaced/moved?
No.
Moreover, I wouldn't recommend this.
Being explicit is always better so IMHO var is only good when the cost of being explicit is too high. This is only the case with lengthy LHS where the same information is repeated on the RHS.
Use diamond operator (or factories). Not that var list = new ArrayList<>() can't work as you removed the type parameters from both sides.
Prefer val to var. With val not being longer than var, there's no reason not to use it (unlike when separate final is needed). This way, you can see what variables may change.
I'd bet the Lombok authors would agree with me, so they won't support such a feature. I hope the same holds for the plugin author.
Related
The Gradle docs for lazy configuration states that in extension/DSL classes, properties like var someProperty = "default value" should actually be val someProperty: Property<String> = objectFactory.property(String::class.java).convention("default value"). This is to avoid unnecessary computation during the configuration phase;
I wonder if there is any downside in using plain types for simple values. The benefits are clear to me in case of computation or I/O, but if anything, for simple values I’d say a plain type would result in slightly less resource use during configuration (one less object created and no method calls).
The main reasons I prefer plain property types for simple values is simplicity and especially that the assignment operator can be used in a build script with Kotlin DSL, e.g. someProperty = "foo". I find this cleaner than someProperty.set("foo") and the latter is also imperative, while Gradle DSLs are otherwise mostly declarative.
It seems to work fine and in the task there would still be a Property<String> counterpart that can be initialized with someProperty.set(extension.someProperty), but since the documentation doesn’t mention it as a possibility for simple values, I’m wondering if there is a good reason for it that I couldn’t think of.
In addition to avoiding unnecessary computation during the configuration phase, using a property allows you to avoid race conditions with afterEvaluate clauses. Extension values set by build scripts are NOT available at configuration time.
Therefore, your example of task.someProperty.set(extension.somePlainField) will not work.
Using task.someProperty.set(extension.someProperty) (the method with signature set(value: Provider<T>)) makes sure that extension.someProperty.get() is not invoked until the task executes and reads its Property.
in order to achieve your goal of a fluent extension api, the recommended approach is to add a method to your extension such as
fun someProperty(value: String) {
someProperty.set(value)
}
then, build scripts can use it like:
myExtension {
someProperty("my value")
}
Suppose I have a function (in Kotlin over Java):
fun <E> myFun() = ...
where E is a general type I know nothing about. Can I determine within this function whether there exists an extension function E.extFun()? And if so, how?
I very much doubt this is possible.
Note that extension functions are resolved statically, at compile time.
And that they're dependent on the extension function being in scope, usually via a relevant import. In particular, it's possible to have more than one extension function with the same name for the same class, as long as they're defined in different places; the one that's in scope will get called.
Within your function, you won't have access to any of that context. So even if you use reflection (which is the usual, and much-abused, ‘get out of jail free card’ for this sort of issue), you still won't be able to find the relevant extension function(s). (Not unless you have prior knowledge of where they might be defined — but in that case, you can probably use that knowledge to come up with a better approach.)
So while I can't say for certain, it seems highly unlikely.
Why do you want to determine this? What are you trying to achieve by it?
I'm wondering if there is a way to let IDE suggest methods before variables?
When writing code like this it's a pain to select methods yourself (builder class example)
Variable example:
var message = "message"
private set
Thank you
Sorry, it appears you can't reconfigure the IDE or Kotlin plugin in this way. You can file a feature suggestion for Kotlin plugin, but I believe there are cases when variables are preferred over same-named methods, so just reordering them would break someone else's habits, so it's tricky.
You can consider making the variables private (so they won't be shown in the completion list at all) or selecting them and then typing an opening parenthesis manually.
I am in the process of learning Kotlin, and reading about the lateinit keyword makes me doubt its usefulness. Consider this code:
var testString: String? = null
lateinit var lateTestString: String
fun print() {
print(testString?.length)
print(lateTestString.length)
}
Here the only difference in getting the length of the string is by checking if it is null or not by using the ?. operator. Is using the lateinit a shortcut for not having to add that extra question mark when accessing properties or invoking methods? Just by that fact I think it is more worth having to add that extra question mark than getting an exception when accessing the lateinit one.
More research showed me that lateinit is good for injections and/or unit tests where the variable has not been initialized yet, but it will be. However, is it not worth having that extra ?. instead of just . to not risk an exception?
lateinit keyword exists to enable one specific scenario: when your field can't be null, but you also can't initialize it in the constructor or with a constant value. It is on you to make sure that you initialize the value before using it. If you don't, you get a special exception with clear meaning.
The difference between lateinit usage and "normal" nullable field with ?. is that the latter conveys a wrong message about the code: "this thing can sometimes be null". When, in fact, it can't. It is just initialized later than usual (with dependency injection instead of constructor, for example).
Is using the lateinit a shortcut for not having to add that extra question mark
Actually it's much closer to a shortcut for !!. I use it a lot in my code, for the reasons I'll try to describe.
Those two !! have been chosen deliberately to attract attention to places in the code where you "take a bet against the type system", so to speak. When used at proper places, that's exactly what you want, but what about all those vars in real-life projects which are effectively non-null, just the type system is too weak to prove it? I'd hate to see the proliferation of !! all around my codebase when I can easily ascertain they are initialized. This noise would weaken the strong signal that !! sends.
When you see a lateinit var in the code, you know you just have to look up whatever initialization method the surrounding context specifies, to convince yourself that everything's fine. It is very easy to check it's used correctly and I've never seen a bug stemming from it.
It is actually very pleasing to see the Kotlin designers putting the concerns of the real-life developer above strict type formalisms.
I'm not from the Jetbrains team, so maybe I don't have a clear picture here, but I agree with you in that lateinit looks like not a good construct.
The original idea when lateinit was added was that we have some frameworks (hint: Android) where occasionally the user of the framework does not have the access to the class's constructors (hint: Android's Activity class), to he can not initialize some property in the constructor or init block. But, due to the fact that these classes have some kind of lifecycle, we can be sure that the property foo will be initialized before it's been used for the first time, because, for example, initialization happens in onCreate(), while the property is used in onResume(), which happens later.
(Somewhere in the past, L - lazy programmer, J - Jetbrains):
L: Hey, Jetbrains! We're lazy, we don't want that extra question mark if we're sure the property will be initialized. Could we please mark it somehow to overcome Kotlin's null safety?
J: Yes, sure! Let's slap in lateinit modifier.
Wonderful idea?
No.
Because in later versions of the language its creators decided to add new syntax for the lateinit properties. I could be wrong (didn't pay much attention to it), but it looks like foo::isInitialized. The reason is that this modifier is being misused (or maybe it's flawed from the very beginning?), so we need to attach some additional checks to it.
So, basically, we're trading the question mark along with the whole null safety for the wonderful opportunity to perform foo::isInitialized checks to prevent UninitializedPropertyAccessException (or something).
lateint means later initialize
in this code you get error.
You have to initialize the lateTestString before calling it.
var testString: String? = null
lateinit var lateTestString: String
fun print() {
print(testString?.length)
print(lateTestString.length)
}
I'm using Twitter Bootstrap on a project at the moment, including the LESS files and compiling with some additional LESS code that we've written.
The latest release has meant we need to override some of the Bootstrap LESS variables. One option here was to maintain a modified copy of Bootstrap which we patch on each release.
But I note that it's possible to override a variable defined in an #import LESS file by re-declaring the variable after the import statement.
E.g.:
#import "twitter-bootstrap/bootstrap.less";
// Restore base font size to pre 2.1.1 defaults
#baseFontSize: 13px;
// Add some custom LESS code here
Is this bad practice? Is it an artifact of the way the LESS compiler works, or an intended part of it? I couldn't find much information on this, although I did find the following two references:
Because of a bug in the Less compiler, you can override the “constant” value of a variable by changing it after it is initially declared.
http://rubysource.com/how-to-customize-twitter-bootstrap%E2%80%99s-design-in-a-rails-app
and
Customize the columns and gutters by overriding these three variables (after the grid.less import has been declared).
http://semantic.gs/
The LESS site itself says that variables are 'constants':
http://lesscss.org/
Note that variables in LESS are actually ‘constants’ in that they can only be defined once.
But then I see other sites using this approach.. It's certainly easier than maintaining a vendor branch and seems to work fine with less.js.
Would appreciate any thoughts on whether this is a bad thing to do or not!
Ok! One of the above issues led to a discussion of the intended behaviour, and it turns out that overriding LESS variables is fine.
Your declarations will overwrite each-other in the same scope in CSS; The same is true for LESS.
https://github.com/cloudhead/less.js/issues/297
Like in CSS, overriding within a scope is an intended way to use LESS.
It´s ok!
I usually create a less file with "components" and variables with a default value. Then I import after that a file with same variables but "customers" values, overwritting default ones. In that way i have only to change some values to create a new design for each customer.
It´s ok and very useful.