Kotlin: Why is defining a field as "var"/"val" needed in constructor? - syntax

This is giving an error:
class Apple(weightInGrams: Float){
fun grow() {
weightInGrams+= 2.0f
}
}

First of all, the equivalent of void (in Java) is Unit (in Kotlin), and the type a function returns goes at the end, so you should use fun grow(): Unit { ... } instead of fun void grow() { ... }. Moreover, you can omit Unit and just write fun grow() { ... } because the compiler knows that your function doesn't return any meaningful value.
Now, I'll try to explain the basics to answer your question and give you some clarity. In Java, the parameters of a constructor are visible only inside that constructor. In Kotlin, the parameters are only visible in initializer blocks and in property initializers, unless you transform them into properties. Let's explain all this with examples.
In Java, we see constructors in classes like this many times:
public class Person {
public final String name;
public final Integer age;
public Person(String name, Integer age) {
this.name = name;
this.age = age;
}
}
The parameters are used to initialize the fields of the class Person.
In Kotlin, the equivalent could be:
a) Use the parameters in initializer blocks.
class Person(name: String, age: Int) {
val name: String
val age: Int
init {
this.name = name
this.age = age
}
}
b) Use the parameters in property initializers declared in the class body.
class Person(name: String, age: Int) {
val name = name
val age = age
}
c) Declaring properties and initializing them directly in the primary constructor.
class Person(val name: String, val age: Int)
Therefore, if you write var or val, the parameters of the constructor will be also properties and you will be able to use them in your class like you want to do inside your function grow.
So, your final code should be:
class Apple(var weightInGrams: Float) {
fun grow() {
weightInGrams += 2.0f
}
}
var because you are assigning a value to weightInGrams multiple times.

make your property a class member
class Apple(var weightInGrams: Float){
fun void grow() {
weightInGrams+= 2.0f
}
}

I understand the question was already answered.
If you want to initialize an apple with an initialWeight, you can do it as below. The init block can help initialize the value and the grow function can effectively work on the actual variable without a need to declare the constructor variable as var:
class Apple(initWeight: Float){
var weightInGrams = 0.0f
init {
var weightInGrams = initWeight
}
fun grow() {
weightInGrams+= 2.0f
}
}
fun main(args: Array<String>) {
val a = Apple(10.0f)
a.grow()
println(a.weightInGrams)
};

Related

What does ContainingType mean in java method reference

In Java Method References
ContainingClass::staticMethodName - means that a class can refer the static method (Reference to a Static Method )
containingObject::instanceMethodName - means that a class object is created first and then that object is used to refer the instanceMethod .
My doubt is
ContainingType::methodName - what does the ContainingType mean ?
Is ContainingType a predefined class in java like String or something else ?
Java Language Specification, §4.3. Reference Types and Values:
There are four kinds of reference types: class types (§8.1), interface types (§9.1), type variables (§4.4), and array types (§10.1).
Array type don't have static methods, so that doesn't apply to static method reference, but you can do the other 3:
class MyClass {
static void doIt() {/*doing it*/}
}
interface MyInterface {
static void doIt() {/*doing it*/}
}
class Test<T extends MyClass> {
void test() {
Runnable m1 = MyClass::doIt; // class type
Runnable m2 = MyInterface::doIt; // interface type
Runnable m3 = T::doIt; // type variable
}
}
Now that link is provided in a comment, it says:
Reference to a static method
ContainingClass::staticMethodName
Reference to an instance method of a particular object
containingObject::instanceMethodName
Reference to an instance method of an arbitrary object of a particular type
ContainingType::methodName
Reference to a constructor
ClassName::new
Here, again, ContainingType refers to any of the 3 reference types mentioned above: Class, Interface, and Type Variable.
You can then make a method reference for any instance method of such a type.
class MyClass {
void doIt() {/*doing it*/}
}
interface MyInterface {
void doIt();
}
class Test<T extends MyClass> {
void test() {
Consumer<MyClass> m1 = MyClass::doIt;
Consumer<MyInterface> m2 = MyInterface::doIt;
Consumer<T> m3 = T::doIt;
}
}
https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html
In the document you gave,there is a example of the ContainingType:
String[] stringArray = { "Barbara", "James", "Mary", "John",
"Patricia", "Robert", "Michael", "Linda" };
Arrays.sort(stringArray, String::compareToIgnoreCase);
and explains:
The equivalent lambda expression for the method reference String::compareToIgnoreCase would have the formal parameter list (String a, String b), where a and b are arbitrary names used to better describe this example. The method reference would invoke the method a.compareToIgnoreCase(b).
I think,the element of the stringArray dosen't have a name (eg: String s1 = "Barbara"),so you can't refer it by containingObject::instanceMethodName(eg:s1::compareToIgnoreCase). That's why it uses ContainingType.
I think your ContainingType::methodName is a general/common form of the 2 forms above...
Think about the below code. You can replace the <methodReference> width
InterfaceA::method (for ContainingType::methodName)
ClassA::method (for also ContainingType::methodName)
ClassB::instanceMethod (for ContainingObject::instanceMethodName) or
ClassB::staticMethod (for ContainingClass::staticMethodName)
to demonstrate the mentioned cases:
public class App {
interface InterfaceA {
String method();
}
static class ClassA implements InterfaceA {
public String method() {
return "ContainingType::methodName";
}
}
static class ClassB extends ClassA {
public String instanceMethod() {
return "ContainingObject::instanceMethodName";
}
public static String staticMethod(ClassB classB) {
return "ContainingClass::staticMethodName";
}
}
public static void main(String[] args) {
System.out.println(((Function<ClassB, String>) <methodReference>).apply(new ClassB()));
}
}

Sort a list of objects based on a parameterized attribute of the object

Assuming that we have an object with the following attributes:
public class MyObject {
private String attr1;
private Integer attr2;
//...
public String getAttr1() {
return this.attr1;
}
public Integer getAttr2() {
return this.attr2;
}
}
One way of sorting a list mylist of this object, based on its attribute attr1 is:
mylist.sort(Comparator.comparing(MyObject::getAttr1));
Is it possible to use this code inside a method in a dynamic way and replace the getAttr1 part with a method that returns the getter of an attribute of the object based on its name? Something like:
public void sortListByAttr(List<MyObject> list, String attr) {
list.sort(Comparator.comparing(MyObject::getGetterByAttr(attr)));
}
The MyObject::getGetterByAttr(attr) part does not compile, I wrote it just as an example to explain my idea
I tried to implement a method with the following code new PropertyDescriptor(attr, MyObject.class).getReadMethod().invoke(new MyObject()) but It's still not possible to call a method with a parameter from the comparing method
You could add a method like
public static Function<MyObject,Object> getGetterByAttr(String s) {
switch(s) {
case "attr1": return MyObject::getAttr1;
case "attr2": return MyObject::getAttr2;
}
throw new IllegalArgumentException(s);
}
to your class, but the returned function is not suitable for Comparator.comparing, as it expects a type fulfilling U extends Comparable<? super U> and while each of String and Integer is capable of fulfilling this constraint in an individual invocation, there is no way to declare a generic return type for getGetterByAttr to allow both type and be still compatible with the declaration of comparing.
An alternative would be a factory for complete Comparators.
public static Comparator<MyObject> getComparator(String s) {
switch(s) {
case "attr1": return Comparator.comparing(MyObject::getAttr1);
case "attr2": return Comparator.comparing(MyObject::getAttr2);
}
throw new IllegalArgumentException(s);
}
to be used like
public void sortListByAttr(List<MyObject> list, String attr) {
list.sort(getComparator(attr));
}
This has the advantage that it also may support properties whose type is not Comparable and requires a custom Comparator. Also, more efficient comparators for primitive types (e.g. using comparingInt) would be possible.
You may also consider using a Map instead of switch:
private static Map<String,Comparator<MyObject>> COMPARATORS;
static {
Map<String,Comparator<MyObject>> comparators=new HashMap<>();
comparators.put("attr1", Comparator.comparing(MyObject::getAttr1));
comparators.put("attr2", Comparator.comparing(MyObject::getAttr2));
COMPARATORS = Collections.unmodifiableMap(comparators);
}
public static Comparator<MyObject> getComparator(String s) {
Comparator<MyObject> comparator = COMPARATORS.get(s);
if(comparator != null) return comparator;
throw new IllegalArgumentException(s);
}
More dynamic is only possible via Reflection, but this would complicate the code, add a lot of potential error source, with only little benefit, considering that you need only to add one line of source code for adding support for another property in either of the examples above. After all, the set of defined properties gets fixed at compile time.
You could also have a single place where this comparators would be defined:
static enum MyObjectComparator {
ATTR1("attr1", Comparator.comparing(MyObject::getAttr1));
MyObjectComparator(String attrName, Comparator<MyObject> comparator) {
this.comparator = comparator;
this.attrName = attrName;
}
private final Comparator<MyObject> comparator;
private final String attrName;
private static MyObjectComparator[] allValues = MyObjectComparator.values();
public static Comparator<MyObject> findByValue(String value) {
return Arrays.stream(allValues)
.filter(x -> x.attrName.equalsIgnoreCase(value))
.map(x -> x.comparator)
.findAny()
.orElseThrow(RuntimeException::new);
}
}
And your usage would be:
public void sortListByAttr(List<MyObject> list, String attr) {
list.sort(MyObjectComparator.findByValue(attr));
}

Understanding method references [duplicate]

This question already has an answer here:
lambda with non-static methods in Java 8
(1 answer)
Closed 6 years ago.
I have the following example:
public class App {
public static void main( String[] args ) {
List<Car> list = Arrays.asList(new Car("green"), new Car("blue"), new Car("white"));
//Ex. 1
List<String> carColors1 = list.stream().map(CarUtils::getCarColor).collect(Collectors.toList());
//Ex. 2
List<String> carColors2 = list.stream().map(Car::getColor).collect(Collectors.toList());
}
static class CarUtils {
static String getCarColor(Car car) {
return car.getColor();
}
}
static class Car {
private String color;
public Car(String color) {
this.color = color;
}
public String getColor() {
return color;
}
}
}
Ex. 1 works since method getCarColor in CarUtils class has the same method signature and return type as apply method in Function interface.
But why Ex. 2 works? Method getColor in Car class has a different from apply method signature and I expect to get a compile time error here.
Method getColor in Car class has a different from apply method signature and I expect to get a compile time error here.
Not really. Car.getColor() is an instance method. You can see it as a function that takes one argument: this, of type Car, and returns a String. So that matches with the signature of apply() in Function<Car, String>.

Grails: How to put a minSize constraints on map

I have this object
#Validateable
class Foo {
Map<String, String> items
static constraints = {
items minSize: 1
}
}
but this test fail:
#Test
void shouldNotValidateIfItemsIsEmpty() {
Foo foo = new Foo(items: [:])
assert !foo.validate()
}
What do I do wrong? It's supposed to work according to grails 'minSize' documentation: "Sets the minimum size of a collection or number property."
The documentation might be misleading. The minSize constraint will only apply to:
String
Arrays
Classes which implements the java.util.Collection interface
java.util.Map however does not extend the java.util.Collection interface
See the supports method of MinSizeConstraint:
public boolean supports(Class type) {
return type != null && (
String.class.isAssignableFrom(type) ||
Collection.class.isAssignableFrom(type) ||
type.isArray());
}
You can develop your own custom constraint for this or a custom validator as suggested by Thermech
In addition, in order for Grails to mock the validate method properly your test class should be something like:
#TestMixin(ControllerUnitTestMixin) class FooTest {
#Test
void shouldNotValidateIfItemsIsEmpty() {
Foo foo = mockCommandObject Foo
foo.items = [:]
assert !foo.validate()
} }
The only way I found, is with a custom validator:
static constraints = {
items validator: { Map map, obj, errors ->
if (map.size() < 1) errors.rejectValue('items', 'minSize.notmet')
}
}

How do i find interfaces that are anyhow related to the class?

I have an issue, i need to list all the interfaces that are anyhow related to the class? –
For ex:
class Test : interface1
{
public int var1;
classA obj1;
classB obj2;
classC obj3;
}
class classA: interface2
{
testclass obj;
}
class classB: interface3
{
}
class classC: interface4
{
}
class testclass: testinterface
{
myinterface objInterface;
}
interface myinterface{}
My question is how do I list all the interfaces of class Test (it should return all the interfaces anyhow related to the class ex:. interface1, interface2 etc.,).
Anyone help me please?
Thanks in advance
With your current code (almost nothing public, fields instead of properties, etc...), you could do something like that :
var type = typeof(Test);
var interfaces = type.GetInterfaces().ToList();
interfaces.AddRange(type.GetFields(BindingFlags.NonPublic|BindingFlags.Instance)
.SelectMany(x => x.FieldType.GetInterfaces()));
this won't retrieve interfaces of public int var1, as it's... public.
This probably won't fit your exact needs, but without real code and real expected result, it's quite hard to give a better answer.
EDIT
With recursion and your sample, in a console app :
private static void Main()
{
var type = typeof(Test);
var interfaces = type.GetInterfaces().ToList();
GetRecursiveInterfaces(type, ref interfaces);
}
private static IList<Type> GetFieldsType(Type type)
{
return type.GetFields(BindingFlags.NonPublic | BindingFlags.Instance).Select(m => m.FieldType).ToList();
}
private static void GetRecursiveInterfaces(Type type, ref List<Type> interfaces)
{
foreach (var innerType in GetFieldsType(type))
{
interfaces.AddRange(innerType.IsInterface
? new[] { innerType }
: innerType.GetInterfaces());
GetRecursiveInterfaces(innerType, ref interfaces);
}
}

Resources