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.
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)
}
}
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
}
}
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);
}
}
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());
}
}
I will write from now on.
Recommended Posts