Histoire de remplacement C # et Java

Par chance, j'ai réexaminé les spécifications de remplacement C # et Java et le comportement du nouveau modificateur spécifique à C # (et C ++), donc je le posterai. Veuillez noter que l'auteur est passé de C # à Java (Android) et écrit du côté Java.

Conclusion d'abord

  1. En principe, toutes les méthodes ** ne peuvent pas être remplacées **
  2. Lors du remplacement, utilisez les qualificatifs virtual et override par paires
  3. Override est "l'extension" de la classe, le nouveau modificateur est le "caché" des membres de la classe et le concept apparié
  1. En principe, toutes les méthodes sont ** remplaçables ** (sauf lorsqu'elles sont déclarées définitives)
  2. Pour remplacer, ajoutez simplement l'annotation Remplacer
  3. Aucun nouveau modificateur (nouvel opérateur uniquement)

Regardons chacun d'eux.

1. Est-il possible de passer outre en principe? impossible?

Il semble que la différence entre C # et Java vient du concept de conception. La citation suivante concerne C ++, mais il semble qu'elle ait été reportée en C #.

En C ++, les fonctions virtuelles ont généralement l'inconvénient d'avoir de moins bonnes performances que les appels de fonction membres réguliers car il n'est pas possible de déterminer quelle fonction membre appeler au moment de la compilation. Par conséquent, les programmeurs C ++ soucieux des performances sont très réticents à ajouter des modificateurs virtuels aux fonctions membres de classe qui n'ont pas besoin d'être héritées. [wiki: Méthode (informatique)](https://ja.wikipedia.org/wiki/%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89_(%E8%) A8% 88% E7% AE% 97% E6% A9% 9F% E7% A7% 91% E5% AD% A6))

pour,

Java est virtuel par défaut [wiki: Méthode (informatique)](https://ja.wikipedia.org/wiki/%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89_(%E8%) A8% 88% E7% AE% 97% E6% A9% 9F% E7% A7% 91% E5% AD% A6))

Donc, toutes les méthodes sont remplaçables par défaut. Notez que «virtuel» fait référence aux membres avec le modificateur virtuel en C #, et indique qu'ils peuvent être remplacés (détails dans la section suivante).

2. Comparaison de l'écriture des remplacements

Pour C

En principe, la substitution n'est pas possible en C #, il existe donc les restrictions suivantes lors de la substitution.

  1. La méthode remplacée nécessite ** un modificateur virtuel **
  2. ** modificateur de remplacement ** requis lors du remplacement dans une classe dérivée

La notation est la suivante.

class Parent {
    //Méthode remplacée
    public virtual void Hoge() {...}
}

class Child : Parent { //Hériter du parent
    public override void Hoge() {...} //passer outre
}

Pour Java

D'un autre côté, Java peut être remplacé en principe, donc ne faites rien à la méthode remplacée et ajoutez l'annotation Override du côté de la classe dérivée pour la remplacer.

class Parent {
    //Méthode remplacée
    public void hoge() {...}
}

class Child extends Parent { //Hériter du parent
    //Remplacer avec l'annotation de remplacement
    @Override
    public void hoge() {...}
}

3. Quel est le nouveau modificateur

Maintenant, avec ce qui précède à l'esprit, jetons un coup d'œil à la référence C #.

new et override ont des significations contradictoires, donc utiliser ces deux modificateurs sur le même membre entraînera une erreur. Le nouveau modificateur crée un nouveau membre avec le même nom et masque le membre d'origine. Le modificateur de remplacement étend l'implémentation des membres hérités. nouveau modificateur (référence C #)

Contrairement au remplacement, le nouveau modificateur masque le membre sous-jacent [^ 1], mais exécutons en fait le programme de console pour le vérifier.

class Program {
    static void Main(string[] args) {
        Parent parent = new Parent();
        Child child = new Child();
        Parent childInParent = new Child(); //Le comportement de ce gars change

                                        //production
        parent.Hoge();                  //Parent#Hoge()
        parent.VirtualMethod();         //Parent#VirtualMethod()

        child.Hoge();                   //Child#Hoge()
        child.VirtualMethod();          //Child#VirtualMethod()

        childInParent.Hoge();           //Parent#Hoge()← Sorties parents (* 1)
        childInParent.VirtualMethod();  //Child#VirtualMethod()

        Console.ReadLine();
    }
}

public class Parent {
    public void Hoge() {
        Console.WriteLine("Parent#Hoge()");
    }

    //Les modificateurs virtuel et de remplacement sont jumelés (* 3)
    public virtual void VirtualMethod() {
        Console.WriteLine("Parent#VirtualMethod()");
    }
}

public class Child : Parent {
    //Masquer avec un nouveau modificateur (* 2)
    public new void Hoge() {
        Console.WriteLine("Child#Hoge()");
    }

    //Remplacer (* 3)
    public override void VirtualMethod() {
        Console.WriteLine("Child#VirtualMethod()");
    }
}

Toutes les méthodes C # sont des méthodes non virtuelles, donc ** le type de la variable ** détermine la classe de méthode à appeler. Dans le code ci-dessus, je veux appeler Child # Hoge () car la variable childInParent assigne un objet de type Child, mais comme la variable est de type Parent, Parent # Hoge () est appelée. C'est parti (* 1).

D'autre part, la variable de type Child child génère Child # Hoge () lors de l'appel de Hoge (). Cela semble évident, mais cela indique que Parent # Hoge () a été ** caché ** par la méthode Child # Hoge () du même nom (* 2).

En outre, lors du remplacement, un qualificateur virtuel est ajouté pour créer une méthode virtuelle et la classe dérivée est implémentée avec le qualificatif de remplacement (* 3).

Résumé

Depuis que j'ai écrit la conclusion en premier, il n'y a pas de résumé, mais du marais de Java, vous vous demandez peut-être pourquoi il existe une fonction si similaire à un tel remplacement. Je pense que les avantages de C # du point de vue de Java sont les suivants.

  1. Empêcher la dégradation des performances due à la virtualisation
  2. Indiquer explicitement les méthodes remplaçables

S'il y a des erreurs, nous les corrigerons. Je vous serais reconnaissant si vous pouviez me dire les avantages. Merci pour la lecture.

[^ 1]: les propriétés, les membres de champ, etc. peuvent également être virtualisés, mais omis car la méthode semble être la plus utilisée

Recommended Posts

Histoire de remplacement C # et Java
[Java] HashCode et remplacement égal
Crypter avec Java et décrypter avec C #
[Java] Que sont les remplacements et les surcharges?
Histoire statique Java
noyau java: compilateur HotSpot et tas C
Lier le code Java et C ++ avec SWIG
Java et JavaScript
XXE et Java
La direction de Java dans "C ++ Design and Evolution"
L'histoire de l'initialiseur Java
De Java à C et de C à Java dans Android Studio
Histoire générique Java
Différences dans l'écriture des classes Java, C # et Javascript
Résumer les différences entre l'écriture C # et Java
Getter et Setter (Java)
[Java] Thread et exécutable
Java vrai et faux
[Java] Comparaison des chaînes de caractères et && et ||
Java - Sérialisation et désérialisation
[Java] Arguments et paramètres
Histoire de support Java 9+ de Lombok
[Java] Branchement et répétition
[Java] Types de variables et types
java (classe et instance)
[Java] Surcharge et remplacement
Organiser les builds dans des combinaisons C ++ / Java et Win / Linux
Langage Java du point de vue de Kotlin et C #
Etudier Java # 2 (\ marque et opérateur)
Java version 8 et fonctionnalités ultérieures
[Java] Aizu Online Judge's story 2
[Java] Histoire du juge Aizu Online 1
Résolution avec Ruby, Perl et Java AtCoder ABC 113 C Reference
[Java] Différence entre == et égal
[Java] Zone de pile et zone statique
[Java] Classe générique et méthode générique
Programmation Java (variables et données)
Cryptage et décryptage Java PDF
Programme de jugement des nombres premiers le plus rapide C # Java C ++
Définition et instanciation de classe Java
[Java] À propos de String et StringBuilder
Kotlin post- et pré-incrémentation et surcharge des opérateurs (comparaison avec C, Java, C ++)
Extension Ruby C et volatile
☾ Instruction Java / Repeat et instruction de contrôle de répétition
Avantages et inconvénients de Java
java (branchement conditionnel et répétition)
Reproduire l'énumération Java en C #
À propos du package Java et de l'importation
Méthodes et classes abstraites Java
Instructions Java while et for
Encapsulation Java et getters et setters
Résolution avec Ruby, Perl et Java AtCoder ABC 129 C (Partie 1)
AtCoder ARC 081 C hash à résoudre en Ruby, Perl et Java
À propos des méthodes Java statiques et non statiques
Aide-mémoire C # pour les techniciens Java
Tutoriels C, Java, JDBC, JSP, Applet
J'ai comparé les constructeurs PHP et Java
Utiliser java avec MSYS et Cygwin
Traçage distribué avec OpenCensus et Java
[Java] Différence entre Hashmap et HashTable