Java - Your own Java base class
Introduction
L'object-oriented programming (programmation orientée objet : une façon d'organiser le code autour d'« objets » qui regroupent des données et des comportements) est un paradigme de programmation populaire inventé au début des années 1960. Kristen Nygaard et Ole-Johan Dahl ont inventé le langage de programmation Simula au Norwegian Computing Center d'Oslo. Le premier langage de programmation orientée objet populaire a été inventé dans les années 1970 au Xerox Palo Alto Research Center (Xerox PARC) par Alan Kay et son équipe.
À la même époque, des langages impératifs et procéduraux ont été inventés. Pascal, inventé par Niklaus Wirth dans les années 1970, et C, inventé par Dennis Ritchie dans les années 1970. Ces langages se compilaient rapidement et offraient une abstraction simple du langage machine. Les deux langages ont été étendus pour supporter la programmation orientée objet dans des versions ultérieures. Pour le langage C, c'est Bjarne Stroustrup qui a inventé le C++ en 1985 comme une extension du C.
Comme tu peux le voir, Java n'est pas le premier langage de programmation orientée objet. Pour comprendre l'orientation objet, nous devons nous pencher sur
Un objet n'est, dans une certaine mesure, guère plus qu'une simple structure de données. Pour commencer, pense à une vraie personne. Nous voulons créer quelques variables pour décrire une personne. Nous décidons d'utiliser une variable pour le prénom (firstname) et une variable pour le nom (lastname).
String firstname;
String lastname;
Il est facile d'ajouter de nouvelles variables avant, après, ou juste entre ces deux variables, des variables qui n'ont peut-être rien à voir avec la personne. Il n'est même pas évident que ces variables décrivent une personne. Pour améliorer notre code, nous construisons une structure qui introduit la personne en tant que concept. L'objet person a deux propriétés, firstname et lastname.
public class Person {
public String firstname;
public String lastname;
}
Repense maintenant aux opérations possibles sur des variables de type String. Il n'y a pas grand-chose que nous puissions en faire. Nous pouvons assigner une nouvelle valeur ou lire la valeur que nous avons assignée à la variable. Nous pourrions rendre cela explicite en fournissant deux méthodes pour chaque variable, une méthode set (set : définir/écrire la valeur) et une méthode get (get : lire la valeur).
public class Person {
public String firstname;
public String lastname;
public void setFirstname(Person person, String firsttname) {
person.firsttname = firstname;
}
public String getFirstname(Person person) {
return person.firstname;
}
// ... same two methods for Lastname
}
Maintenant, si nous avons un objet person, nous avons deux façons d'accéder aux variables dans la structure
Person person = // ...
person.firstname = "Paul";
person.setLasttname(person, "Allen");
Il n'est pas utile de fournir deux façons d'obtenir le même résultat, nous décidons donc de cacher les variables dans la structure. Pour cacher les variables, nous changeons leur visibility modifier (modificateur de visibilité : le mot-clé qui décide qui a le droit d'accéder à la variable) de public à private
public class Person {
private String firstname;
private String lastname;
public void setFirstname(Person person, String firsttname) {
person.firsttname = firstname;
}
public String getFirstname(Person person) {
return person.firstname;
}
// ... same two methods for Lastname
}
La seule façon d'accéder aux variables dans la structure est d'utiliser les méthodes que nous fournissons
Person person = // ...
person.firstname = "Paul"; // Error
person.setLasttname(person, "Allen"); // Ok
Cela nous donne un concept majeur de l'orientation objet : l'encapsulation (regrouper les données et les méthodes ensemble, et contrôler l'accès aux données depuis l'extérieur).
Les méthodes pour set et get les variables de notre structure font partie de la structure elle-même. Nous devons préfixer l'appel de méthode avec la structure de données. Le premier paramètre de toutes les méthodes de la structure est, par convention, toujours la structure elle-même. Si nous utilisons une structure différente, le type changera mais le premier paramètre sera toujours la structure elle-même. D'habitude, nous essayons d'utiliser pour le paramètre un nom qui reflète d'une certaine manière le type du paramètre, mais dans ce cas, nous utilisons une convention différente. Puisque le premier paramètre est toujours la même structure qui possède les méthodes, nous utilisons le mot réservé this (« ceci » : la référence à l'objet courant sur lequel la méthode est appelée).
public class Person {
private String firstname;
private String lastname;
public void setFirstname(Person this, String firsttname) {
this.firsttname = firstname;
}
public String getFirstname(Person this) {
return this.firstname;
}
// ... same two methods for Lastname
}
Puisque nous allons faire cela, encore une fois par convention, pour toutes les structures, le compiler (compilateur : le programme qui traduit ton code source en langage que la machine peut exécuter) ne nous oblige pas à spécifier ce paramètre dans la liste des paramètres. Garde en tête que chaque méthode recevra la structure que nous fournissons avant le nom de la méthode comme premier paramètre, nommé this
C'est souvent une grosse surprise de réaliser que même des programmeurs expérimentés n'ont aucune idée de ce qu'est vraiment this. Si tu as compris ce concept, tu fais un grand pas en avant
Avec l'aide du compiler, nous n'avons plus à spécifier le premier paramètre. En plus, quand nous n'avons qu'une seule variable de la structure nommée firstname et aucun paramètre nommé firstname, nous n'avons pas à préfixer cette variable avec this..
public class Person {
private String firstname;
private String lastname;
public void setFirstname( /* Person this, */ String firsttname) {
this.firsttname = firstname;
}
public String getFirstname( /*Person this */ ) {
return firstname; // this.firstname would be ok, but is not necessary
}
// ... same two methods for Lastname
}
Le code suivant est tout ce que nous avons à écrire. Garde en tête qu'il y a du code que le compiler ajoutera pour nous.
public class Person {
private String firstname;
private String lastname;
public void setFirstname( String firsttname ) {
this.firsttname = firstname;
}
public String getFirstname() {
return firstname;
}
// ... same two methods for Lastname
}
Une fois notre structure terminée, nous pouvons l'utiliser. La seule chose qui reste est l'instantiation (instanciation : créer un objet concret à partir de la classe) de la structure.
Person person = new Person();
person.setFirsttname("Paul");
person.setLasttname("Allen");
L'utilisation des objets est, d'une certaine manière, trompeuse. Pour comprendre le concept de programmation orientée objet
Quand nous déclarons des variables de primitive types (types primitifs : les types de base comme int, boolean, char...), nous pouvons consulter la spécification du langage Java pour déterminer la quantité de mémoire requise pour ce type. Avec une structure, la taille varie et il n'est pas évident de savoir combien de mémoire est nécessaire pour toutes les variables. Pour un type de classe, Java utilise une reference (référence : une « adresse » qui pointe vers l'objet, au lieu de l'objet lui-même) à la place de l'objet réel. La quantité de mémoire requise pour une référence est toujours la même, peu importe la taille de la structure.
class
La class (classe : le plan, le modèle qui décrit à quoi ressemblera un objet) n'est qu'un plan pour un objet. C'est comme un plan d'architecte. Pour une maison, tu ne peux emménager qu'une fois la maison construite à partir du plan créé par un architecte. Si tu pousses l'analogie un peu plus loin, il serait raisonnable de dire qu'un programmeur qui écrit des classes est déjà un architecte logiciel.
instance
L'instance (l'objet concret construit en suivant la description de la classe) est quelque chose qui est construit selon la description de la classe. Avec l'analogie de la maison, c'est la maison qui ressemble à ce qui est décrit dans le plan. Techniquement, l'instance n'est rien de plus que quelques variables dans la mémoire d'un ordinateur.
reference
La reference (référence : ce qui donne accès à une instance, comme l'adresse d'une maison te permet de la retrouver) donne accès à une instance. En Java, nous travaillons en réalité tout le temps avec des références quand nous manipulons des objets, mais nous sommes souvent trop paresseux pour le dire.
Garde en tête que class, instance et reference sont des choses différentes liées à un objet.
Il est possible d'avoir une référence vers un objet, mais aucune instance d'objet. Dans ce cas, la valeur de la référence est null.
null désigne en réalité la première adresse en mémoire. Nous réservons cette adresse pour qu'elle ne référence jamais un vrai objet.
Person person; // reference variable declare, but no instance
new Person(); // will create a lost instance, you can not use it
person = new Person(); // create new instance and assign to reference variable
Person person1 = new Person();
Les variables et méthodes static
Nous avons déjà vu le mot réservé static
Une variable déclarée avec le modificateur static (static : appartient à la classe elle-même, et non à chaque objet créé) ne fait pas partie de l'instance, mais de la classe. Les méthodes déclarées avec le modificateur static ne font pas partie de l'instance, mais de la classe. Cela signifie que :
-
Il n'y a pas de this pour les méthodes static, le paramètre caché est absent des méthodes static
-
Tu devrais accéder aux méthodes static avec le nom de la classe, pas avec une référence d'objet (même si Java l'accepte)
Introduction
Object-oriented programming is a popular programming paradigm invented in the early 1960s. Kristen Nyygaard and Ole-Johan Dahl invented the Simula programming language at the Norwegian Computing Center in Oslo. The first popular object-oriented programming language was invented in the 1970's at the Xerox Palo Alto Research Center (Xerox PARC) by Alan Kay et al.
At the same time, imperative and procedural languages were invented. Pascal, invented by Niklaus Wirth in the 1970's and C, invented by Dennis Ritchie in the 1970's. These languages were fast to compile and provided a simple abstraction over machine language. Both languages were extended to support object-oriented programming in later versions. For the C language, it was Bjarne Stroustrup who invented C++ in 1985 as an extension to C.
As you can see, Java is not the first object-oriented programming language. To understand object orientation, we have to look at
An object is, to a certain degree, not much more than a simple data structure. For a start, think about a real person. We want to create some variables to describe a person. We decide to use one variable for the firstname and one variable for the last name.
String firstname;
String lastname;
It is easy to add new variables before, after, or right between these two variables that may not have anything to do with the person. It is not even clear that the variables describe a person at all. To improve our code, we build a structure that introduces the person as a concept. The person object has two properties, firstname and lastname.
public class Person {
public String firstname;
public String lastname;
}
Now think again about the operations possible on String variables. There is not that much we can do with them. We can assign a new value or read the value we assigned to the variable. We could make this explicit by providing two methods for each variable, a set method, and a get method.
public class Person {
public String firstname;
public String lastname;
public void setFirstname(Person person, String firsttname) {
person.firsttname = firstname;
}
public String getFirstname(Person person) {
return person.firstname;
}
// ... same two methods for Lastname
}
Now, if we have a person object, we have two ways to access the variables in the structure
Person person = // ...
person.firstname = "Paul";
person.setLasttname(person, "Allen");
It is not useful to provide two ways to achieve the same result and we, therefore, decide to hide the variables in the structure. To hide the variables, we change their visibility modifier from the public to private
public class Person {
private String firstname;
private String lastname;
public void setFirstname(Person person, String firsttname) {
person.firsttname = firstname;
}
public String getFirstname(Person person) {
return person.firstname;
}
// ... same two methods for Lastname
}
The only way to access the variables in the structure is using the methods we provide
Person person = // ...
person.firstname = "Paul"; // Error
person.setLasttname(person, "Allen"); // Ok
This provides us with a major concept of object orientation: encapsulation.
The methods to set and get the variables in our structure are part of the structure itself. We have to prefix the method call with the data structure. The first parameter for all methods in the structure is, by convention, always the structure itself. If we use a different structure, the type will change but the first parameter will always be the structure itself. We usually try to use a name for the parameter that, in some way, reflects to the type of the parameter but in this case, use a different convention. Since the first parameter always is the same structure that has the methods, we use the reserved word this.
public class Person {
private String firstname;
private String lastname;
public void setFirstname(Person this, String firsttname) {
this.firsttname = firstname;
}
public String getFirstname(Person this) {
return this.firstname;
}
// ... same two methods for Lastname
}
Since we will do this, again by convention, for all structures, the compiler does not require us to specify this parameter in the parameter list. Keep in mind that every method will receive the structure we provide before the method name as the first parameter named as this
It is often a big surprise to realize that even experienced programmers have no clue what this really is. If you understood this concept, you make a big step forward
With the help of the compiler, we do not have to specify the first parameter anymore. In addition, when we only have one variable from the structure named firstname and no parameter named firstname, we do not have to prefix that variable with this..
public class Person {
private String firstname;
private String lastname;
public void setFirstname( /* Person this, */ String firsttname) {
this.firsttname = firstname;
}
public String getFirstname( /*Person this */ ) {
return firstname; // this.firstname would be ok, but is not necessary
}
// ... same two methods for Lastname
}
The following code is all we have to write. Keep in mind that there is some code that the compiler will add for us.
public class Person {
private String firstname;
private String lastname;
public void setFirstname( String firsttname ) {
this.firsttname = firstname;
}
public String getFirstname() {
return firstname;
}
// ... same two methods for Lastname
}
Once our structure is finished, we can use it. The only thing left is the instantiation of the structure.
Person person = new Person();
person.setFirsttname("Paul");
person.setLasttname("Allen");
The use of objects is in some way misleading. To understand the concept of object-oriented programming
When we declare variables for primitive types, we can look up the Java language specification to determine the amount of memory required for that type. With a structure, the size will vary and it is not clear how much memory is needed for all the variables. For a class type, Java uses a reference instead of the actual. The amount of memory required for a reference is always the same, no matter how large the structure is.
class
The class is only a plan for an object. It's like a blueprint. For a house, you can only move into the house once it is build based on the blueprint an architect created. If you take this analogy a little further, it would be reasonable to say that a programmer that writes classes is already a software architect.
instance
The instance is something that is built according to the description of the class. With the house analogy, this is the house that looks like it is described in the blueprint. Technically, the instance is nothing more than some variables in the memory of a computer.
reference
The reference provides access to an instance. In Java, we actually work with references all the time when we work with objects, but we are often too lazy.
Keep in mind that class, instance and reference are different things related to an object.
It is possible to have a reference to an object, but no instance of an object. In this case, the value of the reference is null.
null actually designates the first address in memory. We reserve this address to never actually reference a real object.
Person person; // reference variable declare, but no instance
new Person(); // will create a lost instance, you can not use it
person = new Person(); // create new instance and assign to reference variable
Person person1 = new Person();
static variables and methods
We already saw the reserved word static
A variable declared with the static modifier is not part of the instance, but part of the class. Methods declared with the static modifier are not part of the instance, but part of the class. This means that:
-
There is no this for static methods, the hidden parameter is missing on static methods
-
You should access static methods with the class name, not with an object reference (though Java will accept this)