What difference does it make when we use get() in Kotlin - java

I want to understand what is the difference at the deeper level between the two statements.
val myVariable: String get() = activity.myName
val myVariable: String = activity.myName
What difference does the get() makes even though I am able to access these variables from other classes and for me both works the same.

It helps to understand it better if you move your get() = to the next line.
val myVariable: String
get() = activity.myName
Because then you'll see that you can also do this:
val myVariable: String = "something"
get() = activity.myName
There are two things going on when you are defining a property.
= "something" or = activity.myName right after the property name and type is the backing field initializer. When you include this, the property is given a backing field, which is an invisible variable that can hold data for the property to use, and the expression is used to define the initial value to hold in the backing field.
Using get() creates a custom getter. This is a function that is run every time the property is accessed, and whatever the function returns is the value the property is read as. If you omit a custom getter, then it uses a default getter which simply returns the value of the backing field from point 1.
You cannot omit both the field and the custom getter, because then you would have a default getter with no backing field to retrieve, which makes no sense.
So now we can explain three possible ways of writing this property:
val myProperty: String
get() = activity.myName
// Every time you use this property, it looks up the activity property and finds the
// value of the activity's myName property. So if activity was changed to point to
// something else or myName was changed to point to something else, myProperty will
// always return the latest value when it is used.
val myProperty: String = activity.myName
// This property is initialized with the value that activity.myName holds at the time
// the class is instantiated, and it will always return this same original value even
// if activity or myName changes, because the value of the backing field is never changed.
// The value of the backing field can only be changed if you're using a var property.
val myProperty: String = activity.myName
get() = activity.myName
// This property behaves like the first one above, but it also has a useless backing
// field that is holding a reference to the original value of activity.myName. Since
// the custom getter doesn't use the backing field, the backing field can never be
// read, so it's useless.
Here's one possible use case for using both a backing field and a custom getter. If you want to keep a constant value in a backing field like in the second example above, but have some side effect like logging something each time it is accessed, you could use both. The keyword field can be used in a custom getter to access the backing field.
val myProperty: String = activity.myName
get() = field.also { Log.i(TAG, "Retrieved value of myProperty.") }

To add onto Tenfour04's answer, another way you could write your get() version is:
val myVariable: String get() {
return activity.myName
}
And that's clearly a function, right? You call it, it returns a String. When a function is simple and returns a value, you can format it as a single-expression function which looks like this:
// block function
fun something(): String {
return coolString
}
// single-expression function - you can omit the type too, if you like
fun something(): String = coolString
So the single-expression equivalent for your getter is
val myVariable: String get() = return activity.myName
The fact it's a val changes things - there are special getter and setter functions you can add to vals and vars, and you're sort of "tacking on" the function at the end of the variable declaration. Because it's a val, it's a property - you read it like a value, like println(myVariable). It's not a function, so you don't call it like println(myVariable()) or anything.
But in this case, because it has this getter function, under the hood Kotlin is calling that function whenever you read the value. And really, anything can happen in there! The value could be completely different every time. Maybe there's no value stored at all, and the getter just calls some other function to generate a value. But the code reading myVariable doesn't know or care about that - it just accesses the variable, and sees a value.
They're basically equivalent to the Java-style getter and setter functions:
fun getMyVariable(): String {
// or whatever you want to return
return activity.myName
}
fun setMyVariable(value: String) {
// do whatever with the value - store it in a variable, record it in some database, etc
}
Except you don't need to treat them as special and call a function to access them - they look and act just like a plain old variable! (And in fact, if you're calling Java setters and getters named like this, Kotlin will let you access them like properties)
So yeah, both the versions in the original question can be accessed the same way - that's the idea! But one is a basic variable - a val in fact, so it's a fixed value. The other is a getter which can do anything, including returning different values over time, calculating stuff on demand, or even just pointing at other values - maybe you want to give access to the other variable, especially if it's a var, or maybe in some versions of a class property A is identical to property B so it's easier to keep one updated and let the other just say "whatever that one says"

Related

Java getter vs Kotlin getter - any difference?

Lets have these two getters in Kotlin:
data class Foo(var id: String){
val reference get() = Reference("Patient/$id")
}
data class Foo(var id: String){
fun getReference(){ return Reference("Patient/$id") }
}
Does the first one have some performance cons? I like it more, but I am not sure if they are built into same bytecode, or the first one adds more things, because I am basically delaring new variable and not just method.
In your example, they are equivalent behind the scenes (but obviously, you need different syntax for using the property vs. the method). Specifically, Kotlin will generate a backing field if any of the accessors use the field identifier, and the autogenerated get and set accessors do use field. So in order to avoid a backing field, you need to supply your own get accessor and (in the case of a var property) a set accessor, and none of them must use field.
Whether a property has a backing field or not, reading the property turns into a method call to get() behind the scenes, and if it's a var, assigning to the property turns into a method call to set().
Note that it's possible to get into weird situations with var if your accessors are inconsistent: var foo: Int = 3; get() = 42 will always return 42 when you read it, irrespective of the initial value and whatever you might assign to it, because you will get an autogenerated backing field since you omitted the setter, and that's what the autogenerated setter will set.
Using properties instead of Java-style getter/setter methods is strongly preferred in Kotlin.
(Thanks to #AlexeyRomanov for pointing out the specific rules.)

Unable to send instance variable value to a sendkeys() method

Now I have a String variable declared as an instance variable, I'm defining the value to the variable inside a method, but when I try to use the value of the same variable inside another method I get this error:
Keys to send should be a not null CharSequence
Now I cannot event set the return type of first method as String because that method accepts an argument hence that is of no use.
This is my code:
String data;
#Keyword
def getFirstRecord(TestObject listData)
{
List<WebElement> firstRecord = WebUiCommonHelper.findWebElements(listData, 20);
data = firstRecord.get(0).getText();
}
#Keyword
def setSearchData(TestObject obj)
{
WebElement txtSearchBox = WebUiCommonHelper.findWebElement(obj, 20);
txtSearchBox.sendKeys(data);
}
I dont have the reputation to comment so Answering here with possibilities.
Please check below cases for your code to see if these things resolve the issue
Case 1) As mentioned by Nandan A in the comments, check if the method 2 is getting called before method 1.
--> If this is the case then please check your configuraiton for test cases and see why this is happening.
Case 2) If the method 2 is getting called after method 1 as expected by your code.
--> Then as per your coment replied I can see in method 2 the String value is still null. And hence it is possible that this framework is creating new instance of your class for executing your #Keyword implementations everytime. You can solve this in few different ways.
One easiest way to try is make your String variable as static. This way, the value will remain same for all instances, as the static variables are stored on the class level instead of instance level in Java.
Another one can be : from first method write the value in to a properties file, and from the second method read the same properties file and the same key's value.
Let me know if this helps you.

Is it necessary to store a value from a method which is returning a value in java?

Let suppose I have a method
public int dummy(){
return 1;
}
and if I call this method by
dummy();
not
int a = dummy();
will it make any difference? why?
No, it wouldn't make any difference. We call a ton of methods from the JDK ignoring their outputs - List's .remove(int index) removes the element at a given index, and returns what element was removed. It is normal to ignore it and move ahead.
It will still compile, but (assuming that the method is just called in isolation) it'll be pointless, since you can never use the value returned. (At a deeper level, and depending on implementation, it's possible the JVM may optimise away the method call entirely.)
If however you do int a = dummy();, then you can later reference that variable, eg. System.out.println(a); will print out its value.
If your method had another side effect other than returning a value, such as:
public int dummy(){
System.out.println("hello");
return 1;
}
...then calling it without assigning its result to a variable wouldn't be pointless, since the side effect would still occur (printing "hello" in this case). While some argue this is poor design, this sometimes occurs in practice in the Java libraries - you could call createnewFile() on a File object for instance and ignore its returned boolean value (which will tell you whether the file was created or not.)
These two are both true statements, but the difference is, when you use
dummy()
this will call the function in the program, but since you are returning a value, it is pointless ( considering you will keep the value )
When you use
int a = dummy()
You will create an integer named a in order to store the output ( return value ) of the function, which you can reuse any time.

How to get text format of message without filling up fields

I have got my protobuf GeneratedMessage(only castable to this base) and I would like to get the text format(parsable by TextFormat class) including all fields of this message.
I see only two ways:
by reflection find all setters and put in some values, then use TextFormat
get list of fields(from api) and recreate this format
Neither of them is good, so my question is: is there any better way? If not which of these you find better?
If you have a GeneratedMessage, you may simply pass it into any of TextFormat's print methods. GeneratedMessage implements the MessageOrBuilder interface which these methods want.
EDIT: I see, your problem is that you want it to actually print all the fields, and TextFormat only prints fields that have been filled in.
You will have to fill in the fields with dummy data. This is actually pretty easy, though:
Message fillAllFields(Message prototype) {
Message.Builder builder = prototype.newBuilderForType();
for (FieldDescriptor field: builder.getDescriptorForType().getFields()) {
builder.setField(field, prototype.getField(field));
}
return builder.build();
}
The trick here is that we're calling setField() for every defined field, not just the ones that are set in prototype. For the ones that aren't set there, prototype.getField() will return the default value, but we're still explicitly setting the field to that value, so it will now show up in text format. Note that this actually creates a different message from the original -- setting a field to its default value is detectably different from leaving the field unset.

Is there a way in Java to find the name of the variable that was passed to a function?

I have a Java function called testForNull
public static void testForNull(Object obj)
{
if (obj == null)
{
System.out.println("Object is null");
}
}
I use it to test multiple objects to ensure they are not null. But, I am unable to tell the name of the variable that way.
For eg. if I say
testForNull(x);
testForNull(y);
testForNull(z);
I cannot tell which of the three lines caused the "Object is null" output. Of course, I can simply add another parameter to the function and have something like
testForNull(x, "x");
testForNull(y, "y");
testForNull(z, "z");
But I want to know whether it is possible to deduce the name of the variable without passing it explicitly. Thanks.
Consider that the parameter might not have been a variable (and therefore wouldn't have a name):
testForNull(x != y);
No, there is no such a way. You will have to explicitly pass the name of the variable.
However, if your object has a field 'name' or displays its name via the toString() function, then that might help you.
Yes, but I wouldn't recommend it and it would be exceptionally hard. Try assert instead:
http://docs.oracle.com/javase/1.4.2/docs/guide/lang/assert.html
To do what you want, if you have the source code, get the current thread http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#currentThread()
Get a stack trace http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#getStackTrace()
Get the 2nd to last element, the class name, file name, and line number, then print that line, or parse it http://docs.oracle.com/javase/7/docs/api/java/lang/StackTraceElement.html#method_summary
This is what a debugger is for. There is no way to do this programmatically. What if I invoke testForNull(1 + 1). What is the variable name then?
Eclipse has a graphical and easy-to-use debugger for Java built-in. Learning how to use that will pay dividends in the long run, and happens to be the immediate solution to your problem as well.
you could place the method call in a foreach and set a reference ID for each object that you are going through, even if it returns null or not null for that specific object.
Bah, After looking at the original question again, this is a non-starter.
The question asks us to be able to provide a means by which a value passed into a CheckForNull() method can retrieve the values name - and here's the kicker... only when the value is null.
There is absolutely no way you are going to get anything from a null value other than a String containing "null" or a NullPointerException.
But, as usual, object orientation to the rescue. Create a value class like I mentioned above. Now add an isNull() method to it. Use this value class for any value you are wanting to dump debugging text for.
Java is an object oriented language, therefore the answer is "most definitely!" you can tell the name of the variable passed as a parameter. To do so, try this...
class Value<T> extends Object
{
T value;
String name;
public Value(String name, T value)
{
this.name = name;
this.value = value;
}
}
Now in your methods, you would accept all parameters as instances of Value, as in the following method which would accept only Values created with classes having Number as a base class (which would be Long, Float, Double, etc)...
public String SomeMethodWantingToKnowParameterNames(Value<? extends Number> parm1)
{
if (parm1 != null)
{
// Do your work with the parameter - it's name can be accessed via parm1.name
// This is only an example
// You would probably want to write an accessor for name
return parm1.name;
}
// Return null for null
return null;
}
And that is all there is to it! I use a generic class so that Value can be used to pass in any type - Floats, Longs, Double, BigInteger, String - for example...
Value<Float> vFloat = new Value<Float>("MyFloat", 0.0);
Also, the method above is simply an example - in practice any method accepting a Value could access its name.
Good Luck and may all your code compile flawlessly!
Rodney

Categories

Resources