Un ingénieur Java a comparé Swift, Kotlin et Java.

Je tiens une session d'étude Kotlin en interne, et je me demande souvent ce qui se passe lorsque j'écris la grammaire de Kotlin en Swift et Java, alors j'aimerais étudier et dessiner les résultats de l'implémentation. .. C'est une langue différente, donc je pense qu'il est difficile d'être un égal strict, mais pardonnez-moi s'il vous plaît.

Vérification du passage par référence

Kotlin J'ai parlé de la façon de mettre en œuvre le passage par référence dans Kotlin lors d'une session d'étude en interne, alors j'ai essayé une petite vérification.

Il semble que Kotlin ne peut pas être utilisé par référence à moins qu'il ne soit explicitement déclaré mutable. De plus, si vous essayez de l'attribuer à un argument, une erreur de compilation se produira.

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) //Il ne peut pas être attribué à un argument. Une erreur de compilation se produira.
    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 peut être fait en déclarant inout qu'il est passé par référence. Puisqu'elle est passée par référence, la variable tableau peut être réécrite dans la fonction.

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 J'ai essayé de faire la même chose en Java, mais je peux apporter des modifications en utilisant la méthode array, Le tableau affiché par la variable d'origine n'a pas changé même s'il a été nouvellement instancié et affecté dans la méthode de référence.

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>(); //Remplacer ici une nouvelle ArrayList ne modifie pas la portée d'origine.
        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]Ne sera pas)
    }
}

interface

Kotlin Je pensais que l'utilisation de l'interface de Kotlin n'est pas particulièrement différente de Java, mais je pense qu'elle est différente de Java dans le sens où les variables de champ peuvent également être restreintes.

InterfaceTest.kt



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

class English : Lang {
    override val name = "English" //Erreur de compilation si non déclarée
    override fun getHelloWorld(target: String) : String {
        return "Hello, $target!"
    }
}

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

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

Swift Dans le cas de Swift, il semble que Protocol puisse être implémenté comme l'interface Kotlin.

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 "Bonjour, \(target)"
    }
}

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

Java Je ne m'en suis pas rendu compte parce que je ne voulais pas vraiment l'utiliser de cette façon, mais Java ne peut pas forcer une classe réelle à avoir un champ lorsqu'elle définit un champ dans Interface. (Au contraire, il sera forcé d'être une finale staique publique, il sera donc traité comme une constante.)

Lang.java


interface Lang {
    public static final String name = ""; //Les champs définis dans l'interface sont forcés d'être public staic final.
    public String getHelloWorld(String target);
}

English.java


class English implements Lang {
    // public String name; //OK sans déclarer

    @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 "Bonjour, %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")); //Bonjour, world
    }
}

Objet compagnon

Kotlin L'accès statique (statique) en Java et dans d'autres langages peut être implémenté dans Kotlin avec Companion Object.

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() //Créer une entité anglaise avec la méthode Create
    println(Egreeter.getHelloWorld("world"))
}

J'ai essayé diverses choses, mais CompanionObject fonctionne comme suit.

--Un CompanionObject peut être défini dans une classe


class English : Lang {
    override val name = "English"
    override fun getHelloWorld(target: String) : String {
        return "Hello, $target!"
    }
    companion object Factory { //Factory peut être présent ou non, mais requis pour accéder à l'objet compagnon depuis java.
        const val COMPANION_NAME = "Companion" //Vous pouvez définir des constantes.
        val companionName = "test" //Vous pouvez déclarer des variables de champ accessibles statiquement sans ajouter de const.
        fun create(): English = English()
        fun getNameCom(): String {
            // return name //Vous ne pouvez pas accéder au champ anglais depuis l'objet compagnon.
            return companionName  //Les variables de l'objet compagnon sont accessibles
        }
    }
}

Fondamentalement, il semble être recommandé de l'utiliser lors de l'implémentation d'une valeur constante ou d'un modèle Factory tel que la méthode create.

Swift Dans le cas de Swift, le même comportement peut être implémenté en déclarant static. En fait, c'est plus facile à comprendre que de s'en souvenir comme un objet compagnon.

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   //Les variables membres ne sont pas accessibles à partir des fonctions statiques.
    }

}

let Egreeter = English.create()
print(Egreeter.getHelloWorld(target: "world"))
print(English.COMPANION_NAME) //Puisqu'il s'agit d'une constante, on peut y accéder

Java Java peut être construit de la même manière que 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; //Le nom de la variable non statique ne peut pas être référencé à partir du contexte statique. J'obtiens une erreur.
    }
}

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);
    }
}

Héritage de classe et constructeur

Kotlin Pour savoir comment hériter des classes et comment les construire, j'ai créé la classe England et sa classe abstraite Country class, et leur ai donné le nom du pays, la langue et la population comme attributs. De plus, du pays, j'ai dit que je pouvais recevoir des salutations et de la population, et j'ai transféré le traitement réel à la classe réelle de l'interface Lang. (Honnêtement, je pense que la conception de la classe est subtile ...)

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."
    }
}

//Rendre la classe de base obligatoire en lui donnant le nom du pays, la langue et les attributs de population
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 J'ai essayé de le réécrire dans Swift, mais je ne pensais pas que Swift avait l'idée d'une classe abstraite, donc je ne pensais pas qu'il était vraiment nécessaire d'implémenter la classe Country. Je ne recommande pas d'utiliser Protocol comme type (ne pouvez-vous pas dire ça?), J'ai donc forcé la superclasse à ne pas avoir de propriété lang.

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 C'est fondamentalement le même que Kotlin, mais l'accès à la propriété est changé en getter selon la méthode Java. Je pense que le code est plus long que Kotlin de ce montant.

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());
    }
}

Coffre-fort nul

J'écrirai désormais.

Recommended Posts

Un ingénieur Java a comparé Swift, Kotlin et Java.
Ecrire une classe en Kotlin et l'appeler en Java
Je veux faire une liste avec kotlin et java!
Je veux créer une fonction avec kotlin et java!
J'ai comparé les constructeurs PHP et Java
Différences entre Java "débutant" et Kotlin
J'ai comparé Java et Ruby FizzBuzz.
[Java] Créer et appliquer un masque des diapositives
Conversion entre Kotlin nullable et Java facultative
Un regard sur Jenkins, OpenJDK 8 et Java 11
Relation entre les modificateurs d'accès kotlin et java
[Swift] Une note sur la fonction et la fermeture
[Pour les débutants] Différence entre Java et Kotlin
[Java / Swift] Comparaison de l'interface Java et du protocole Swift
Fonctions Kotlin et lambdas à envoyer aux développeurs Java
Instruction de commutation Java et pause, Kotlin lorsque l'expression ...
[Swift vs Java] Comprenons le statique et le final
J'ai comparé les caractéristiques de Java et .NET
Comparaison entre Java et Swift (1) Source control / Scope / Variables
Java et JavaScript
XXE et Java
Préparer un environnement de scraping avec Docker et Java
Comparaison Java et Swift (3) Implémentation de classe / héritage de classe / conception de classe
Veuillez noter la division (division) de java kotlin Int et Int
Envoyez-moi une feuille de route pour devenir un ingénieur Java à part entière
Appeler une méthode avec le bloc de rappel de Kotlin depuis Java
Langage Java du point de vue de Kotlin et C #
Je veux faire des transitions d'écran avec kotlin et java!
Comment convertir A en A et A en A en utilisant le produit logique et la somme en Java
Appeler un programme écrit en Swift depuis Processing (Java)
Créez une application JAVA WEB et essayez OMC APM
[Java] [Kotlin] Appeler valueOf et les valeurs de Enum de manière générique
[Java] Créer un filtre
Java vrai et faux
[Java] Comparaison des chaînes de caractères et && et ||
java construire un triangle
[Java, Kotlin] Variance de type
Java - Sérialisation et désérialisation
[Java] Arguments et paramètres
timedatectl et Java TimeZone
[Java] Branchement et répétition
[Java] Types de variables et types
java (classe et instance)
[Java] Surcharge et remplacement
Attribuer des expressions lambda Java8 aux variables et les réutiliser
Mémorandum n ° 4 "Obtenez une chaîne de caractères et décorez-la" [Java]
[Java] Lancer une requête et afficher l'écran ② (GET / POST)
J'ai essayé de résumer les bases de kotlin et java
[Java] Lancer une requête et afficher l'écran (GET / POST)
[Kotlin] Ressources et conseils pour apprendre un nouveau langage de programmation
Kotlin post- et pré-incrémentation et surcharge des opérateurs (comparaison avec C, Java, C ++)
[Kotlin] Obtenez le constructeur / la méthode Java de KFunction et appelez-le
Comment déployer une application kotlin (java) sur AWS Fargate
Fonctionnalité du langage Java et comment elle a produit un bogue subtil
Même jugement / jugement de valeur égale / comparaison / ordre dans Swift et Java
Ajouter une ombre au bouton Swift (et aussi au cercle)
Comment développer et enregistrer une application Sota en Java