A Java engineer compared Swift, Kotlin, and Java.

I hold a Kotlin study session in-house, and I often get wondering what happens when I write Kotlin grammar in Swift and Java, so I will investigate and draw the results of implementation. .. Since it is a different language, it may be difficult to make a strict equal, but please forgive me.

Verification of passing by reference

Kotlin I talked about how to implement passing by reference in Kotlin at an in-house study session, so I tried a little verification.

It seems that Kotlin cannot be used by reference unless it is explicitly declared to be mutable. Also, if you try to assign it to an argument, a compile error will occur.

ArrayTest.kt


fun addArray(array: MutableList<Int>) {
    array.add(9)
    println(array) // [1, 2, 3, 9]
}

fun changeArray(array: MutableList<Int>) {
    array = mutableListOf(1, 2, 3) //It cannot be assigned to an argument. A compile error occurs.
    println(array)
}

fun main(args: Array<String>) {
    val array = mutableListOf(1, 2, 3)
    println(array) // [1, 2, 3]
    addArray(array)
    println(array) // [1, 2, 3, 9]
}

Swift Swift can be done by declaring inout that it is passed by reference. Since it is passed by reference, the array variable can be rewritten in the function.

ArrayTest.swift


func addArray(array : inout [Int])  {
    array.append(9)
    print(array)  // [1, 2, 3, 9]
}

func substituteArray(array : inout [Int])  {
    array = [100, 200, 300]
    print(array)  //  [100, 200, 300]
}

var array = [1, 2, 3]
print(array)    // [1, 2, 3]
addArray(array: &array)
print(array)    // [1, 2, 3, 9]
substituteArray(array: &array)
print(array)    // [100, 200, 300]

Java I tried to do the same in Java, but I can make changes using the array method, The array shown by the original variable did not change even if it was newly instantiated and assigned in the reference method.

ArrayTest.java


import java.util.ArrayList;

class ArrayTest {
    private static void addArray(ArrayList<Integer> array) {
        array.add(9);
        System.out.println(array); // [1, 2, 3, 9]
    }

    private static void substituteArray(ArrayList<Integer> array) {
        array = new ArrayList<Integer>(); //Substituting a new ArrayList here does not change the original scope.
        array.add(100);
        array.add(200);
        array.add(300);
        System.out.println(array); // [100, 200, 300]
    }

    public static void main(String args[]) {
        ArrayList<Integer> array = new ArrayList<Integer>();
        array.add(1);
        array.add(2);
        array.add(3);
        System.out.println(array); // [1, 2, 3]
        addArray(array);
        System.out.println(array); // [1, 2, 3, 9]
        substituteArray(array);
        System.out.println(array); // [1, 2, 3, 9]([100, 200, 300]Will not be)
    }
}

interface

Kotlin I thought that the usage of Kotlin's interface is not particularly different from Java, but I think that it is different from Java in that field variables can also be restricted.

InterfaceTest.kt



interface Lang {
    val name: String
    fun getHelloWorld(target: String) : String
}

class English : Lang {
    override val name = "English" //Compile error if not declared
    override fun getHelloWorld(target: String) : String {
        return "Hello, $target!"
    }
}

class Japanese : Lang {
    override val name = "Japanese"
    override fun getHelloWorld(target: String) : String {
        return "Hello,$target!"
    }
}

fun main(args: Array<String>) {
        val Elang = English()
    println(Elang.getHelloWorld("world")) // Hello, world!
    val Jlang = Japanese()
    println(Jlang.getHelloWorld("world")) //Hello, world!
    
}

Swift In the case of Swift, it seems that Protocol can be implemented like Kotlin interface.

InterfaceTest.swift


protocol Lang {
    var name : String {get}
    func getHelloWorld(target :String) -> String
}

class English: Lang {
    
    let name = "English"
    func getHelloWorld(target : String)  -> String {
        return "Hello, \(target)"
    }
}

class Japanese: Lang {
    
    let name = "Japanese"
    func getHelloWorld(target : String)  -> String {
        return "Hello, \(target)"
    }
}

let Elang = English()
print(Elang.getHelloWorld(target: "world")) // Hello, world!
let Jlang = Japanese()
print(Jlang.getHelloWorld(target: "world")) //Hello, world

Java I didn't notice it because I didn't really want to use it that way, but Java can't force a real class to have a field when it defines a field in Interface. (Rather, it will be forced to be a public staic final, so it will be treated as a constant.)

Lang.java


interface Lang {
    public static final String name = ""; //The fields defined in the interface are forced to be public staic final.
    public String getHelloWorld(String target);
}

English.java


class English implements Lang {
    // public String name; //OK without declaring

    @Override
    public String getHelloWorld(String target) {
        return "Hello, %TARGET%!".replace("%TARGET%", target);
    }
}

Japanese.java


class Japanese implements Lang {

    @Override
    public String getHelloWorld(String target) {
        return "Hello, %TARGET%!".replace("%TARGET%", target);
    }
}

InterfaceTest.java


class InterfaceTest {
    public static void main(String args[]) {
        English Elang = new English();
        System.out.println(Elang.getHelloWorld("world")); // Hello, world!
        Japanese Jlang = new Japanese();
        System.out.println(Jlang.getHelloWorld("world")); //Hello, world
    }
}

Companion object

Kotlin Static access (Static) in Java and other languages can be implemented in Kotlin with Companion Objects.

CompanionObjectTest.kt


interface Lang {
    val name: String
    fun getHelloWorld(target: String) : String
}

class English : Lang {
    override val name = "English"
    override fun getHelloWorld(target: String) : String {
        return "Hello, $target!"
    }
    companion object Factory { // Companion object
        fun create(): English = English()
    }
}

fun main(args: Array<String>) {
    val Egreeter = English.create() //Create English entity with Create method
    println(Egreeter.getHelloWorld("world"))
}

I tried various things, but Companion Object works as follows.

--One CompanionObject can be defined in one class --Since it is static access, you cannot access the fields and methods of your class from within CompanionObject. You can define constants with --const, or you can declare variables inside companion objects.


class English : Lang {
    override val name = "English"
    override fun getHelloWorld(target: String) : String {
        return "Hello, $target!"
    }
    companion object Factory { //Factory may or may not be present, but required to access the companion object from java.
        const val COMPANION_NAME = "Companion" //You can define constants.
        val companionName = "test" //You can declare field variables that can be statically accessed without const.
        fun create(): English = English()
        fun getNameCom(): String {
            // return name //You cannot access the English field from within the Companion Object.
            return companionName  //Variables in Companion Object can be accessed
        }
    }
}

Basically it seems to be recommended to use a constant value or when implementing a Factory pattern like the create method.

Swift In the case of Swift, the same behavior can be implemented by declaring static. If anything, this is easier to understand than remembering it as a Companion Object.

StaticTest.swift


protocol Lang {
    var name : String {get}
    func getHelloWorld(target :String) -> String
}

class English: Lang {
    
    let name = "English"
    func getHelloWorld(target : String)  -> String {
        return "Hello, \(target)"
    }
    static var COMPANION_NAME = "Companion"
    static func create() -> English {
        return English()
    }
    static func getName() -> String {
        return name   //Member variables cannot be accessed from static functions.
    }

}

let Egreeter = English.create()
print(Egreeter.getHelloWorld(target: "world"))
print(English.COMPANION_NAME) //Since it is a constant, it can be accessed

Java Java can be built in the same way as Swift.

Lang.java


interface Lang {
    public String getHelloWorld(String target);
}

English.java


class English implements Lang {
    public String name = "English";

    @Override
    public String getHelloWorld(String target) {
        return "Hello, %TARGET%!".replace("%TARGET%", target);
    }

    public static final String COMPANION_NAME = "Companion";

    public static English create(){
        return new English();
    }
    public static String getName() {
        return name; //Non-static variable name cannot be referenced from static context I get an error.
    }
}

StaticTest.java


class StaticTest {
    public static void main(String args[]) {
        English Elang = English.create();
        System.out.println(Elang.getHelloWorld("world"));
        System.out.println(English.COMPANION_NAME);
    }
}

Class inheritance and constructor

Kotlin In order to find out how to inherit the class and how to construct it, I created the England class and the Country class of its abstract class, and gave them the country name, language, and population as attributes. Also, from the country, I said that I could get greetings and some population, and I transferred the actual processing to the actual class of Lang interface. (Honestly, I feel that the class design is subtle ...)

ConstructorTest.kt


interface Lang {
    val name: String
    fun getHelloWorld(target: String) : String
    fun getPopulation(countryName: String, population : Int) : String
}

class English : Lang {
    override val name = "English"
    override fun getHelloWorld(target: String) : String {
        return "Hello, $target!"
    }
    override fun getPopulation(countryName: String, population : Int) : String {
        return "$countryName has a population of $population people."
    }
}

//Make the base class mandatory by giving it country name, language, and population attributes
abstract class Country (_name : String, _lang: Lang, _population: Int) {
    val name : String = _name
    val lang : Lang = _lang
    val population = _population
    fun getPopulation() : String {
        return lang.getPopulation(name, population)
    }
}

class England() : Country("England", English(), 53013000)

fun main(args: Array<String>) {
	val country = England()
    
    println(country.name)
    println(country.lang.getHelloWorld("world"))
    println(country.getPopulation())
  
}

Swift I rewrote it in Swift, but I didn't think it was necessary to implement the Country class because Swift doesn't have the idea of an abstract class. I don't recommend using Protocol as a type (can't you say that?), So I forced the superclass not to have a lang property.

ConstructorTest.kt


import Foundation

protocol Lang {
    var name : String {get}
    func getHelloWorld(target :String) -> String
    func getPopulation(countryName: String, population : Int) -> String
}

class English: Lang {
    
    let name = "English"
    func getHelloWorld(target : String)  -> String {
        return "Hello, \(target)"
    }
    
    func getPopulation(countryName: String, population : Int) -> String {
        return "\(countryName) has a population of \(population) people."
    }
}
class Country {
    var name : String = ""
    var population : Int = 0
    init(_name : String, _population : Int) {
        name = _name
        population = _population
    }
}

class England : Country {
    var lang = English()
    
     init() {
        super.init(_name: "England", _population: 53013000)
    }
    
    func getPopulation() -> String {
        return self.lang.getPopulation(countryName: name, population: population)
    }
    
    func getHelloWorld(target: String) -> String {
        return self.lang.getHelloWorld(target: target)
    }
}

var country = England()

print(country.name)
print(country.getHelloWorld(target: "world"))
print(country.getPopulation())

Java It's basically the same as Kotlin, but the property access is changed to getter according to Java's method. I think that the code is longer than Kotlin by that amount.

Lang.java


interface Lang {
    public String getHelloWorld(String target);
    public String getPopulation(String countryName, int population);
}

English.java


class English implements Lang {
    
    private String name = "English";

    public String getName() {
         return name;
    }

    @Override
    public String getHelloWorld(String target) {
        return "Hello, %TARGET%!".replace("%TARGET%", target);
    }

    @Override
    public String getPopulation(String countryName, int population) {
	return  "%COUNTRY_NAME% has a population of %POPULATION% people."
	    .replace("%COUNTRY_NAME%", countryName)
	    .replace("%POPULATION%", Integer.toString(population));
    }

}

Country.java


public abstract class Country {
    private String name;
    private Lang lang;
    private int population;

    public Country(String _name, Lang _lang, int _population) {
        name = _name;
        lang = _lang;
        population = _population;
    }

    public String getPopulation() {
        return lang.getPopulation(name, population);
    }

    public String getName() {
        return name;
    }

    public Lang getLang() {
        return lang;
    }

}

England.java


public class England extends Country {

    public static final String NAME = "England";
    public static final int POPULATION = 53013000;

    public England() {
        super(NAME, new English(), POPULATION);
    }
}

ConstructorTest.java


class ConstructorTest {

    public static void main(String args[]) {
        England country = new England();

        System.out.println(country.getName());
        System.out.println(country.getLang().getHelloWorld("world"));
        System.out.println(country.getPopulation());
    }
}

Null safe

I will write from now on.

Recommended Posts

A Java engineer compared Swift, Kotlin, and Java.
Write a class in Kotlin and call it in Java
I want to make a list with kotlin and java!
I want to make a function with kotlin and java!
I compared PHP and Java constructors
Differences between "beginner" Java and Kotlin
I compared Java and Ruby's FizzBuzz.
[Java] Create and apply a slide master
Conversion between Kotlin nullable and Java Optional
A look at Jenkins, OpenJDK 8 and Java 11
Relationship between kotlin and java access modifiers
[Swift] A note about function and closure
[For beginners] Difference between Java and Kotlin
[Java / Swift] Comparison of Java Interface and Swift Protocol
Kotlin functions and lambdas to send to Java developers
Java switch statement and break, Kotlin when expression ...
[Swift vs Java] Let's understand static and final
I compared the characteristics of Java and .NET
Java and Swift comparison (1) Source control / Scope / Variables
Java and JavaScript
XXE and Java
Prepare a scraping environment with Docker and Java
Java and Swift comparison (3) Class implementation / Class inheritance / Class design
Create a portfolio app using Java and Spring Boot
Please note the division (division) of java kotlin Int and Int
Send me a roadmap to becoming a full-fledged Java engineer
Call a method with a Kotlin callback block from Java
Java language from the perspective of Kotlin and C #
I want to transition screens with kotlin and java!
How to convert A to a and a to A using AND and OR in Java
Call a program written in Swift from Processing (Java)
Create a JAVA WEB application and try OMC APM
[Java] [Kotlin] Generically call valueOf and values of Enum
About synchronized and Reentrant Lock (Java & Kotlin implementation example)
[Java] Create a filter
Java true and false
[Java] String comparison and && and ||
java build a triangle
[Swift 5] Draw a line.
[Java, Kotlin] Type Variance
Java --Serialization and Deserialization
[Java] Arguments and parameters
[Swift] Constants and variables
timedatectl and Java TimeZone
[Java] Branch and repeat
[Java] Variables and types
java (classes and instances)
[Java] Overload and override
Assign a Java8 lambda expression to a variable and reuse it
Memorandum No.4 "Get a character string and decorate it" [Java]
[Java] Throw a request and display the screen ② (GET / POST)
I tried to summarize the basics of kotlin and java
[Java] Throw a request and display the screen (GET / POST)
[Kotlin] Resources and tips for learning a new programming language
Kotlin post- and pre-increment and operator overload (comparison with C, Java, C ++)
[Kotlin] Get Java Constructor / Method from KFunction and call it
How to deploy a kotlin (java) app on AWS fargate
Java Language Feature and How it Produced a Subtle Bug
Same judgment / equal value judgment / comparison / order in Swift and Java
Add a shadow to the Swift Button (and also the circle)
How to develop and register a Sota app in Java