Les Interfaces et les classes Abstraites confusion en Java avec des exemples
Je vais avoir du mal à comprendre quand utiliser une interface, par opposition à une classe abstraite, et vice-versa. Aussi, je suis confus quand pour étendre une interface avec une autre interface. Désolé pour le long post, mais c'est très déroutant.
Création de formes apparaît comme un point de départ populaire. Disons que nous voulons un moyen de modéliser les formes en 2D. Nous savons que chaque forme aura une zone. Quelle serait la différence entre les deux implémentations:
avec des interfaces:
public interface Shape {
public double area();
}
public class Square implements Shape{
private int length = 5;
public Square(){...}
public double area()
return length * length;
}
}
avec classe abstraite:
abstract class Shape {
abstract public double area();
}
public class Square extends Shape {
private length = 5;
public Square(){...}
public double area(){
return length * length;
}
Je comprends que les classes abstraites permet de définir des variables d'instance et vous permet de donner des implémentations de méthode alors qu'une interface ne peut pas faire ces choses. Mais dans ce cas, il semble que ces deux versions sont identiques. Donc, en utilisant tout est beau?
Mais maintenant, de dire que nous voulons décrire les différents types de triangles. Nous pouvons avoir une isocèle, aiguë, et des triangles rectangles. Pour moi, il est logique d'utiliser l'héritage de classe dans ce cas. En utilisant le 'EST-A' définition: un Triangle rectangle "EST-UN" Triangle. Un Triangle "EST-UN" de Forme. Aussi, une classe abstraite doit définir les comportements et les attributs qui sont communs dans toutes les sous-classes, donc c'est parfait:
avec classe abstraite
abstract Triangle extends Shape {
private final int sides = 3;
}
class RightTriangle extends Triangle {
private int base = 4;
private int height = 5;
public RightTriangle(){...}
public double area() {
return .5 * base * height
}
}
Nous pouvons faire cela avec les interfaces ainsi, avec le Triangle et la Forme des interfaces. Cependant, contrairement à l'héritage de classe (en utilisant "EST-UN" de la relation de définir ce que devrait être une sous-classe), je ne suis pas sûr de savoir comment utiliser une interface. Je vois deux façons:
Première façon:
public interface Triangle {
public final int sides = 3;
}
public class RightTriangle implements Triangle, Shape {
private int base = 4;
private int height = 5;
public RightTriangle(){}
public double area(){
return .5 * height * base;
}
}
Deuxième façon:
public interface Triangle extends Shape {
public final int sides = 3;
}
public class RightTriangle implements Triangle {
....
public double area(){
return .5 * height * base;
}
}
Il me semble que ces deux façons de travailler. Mais quand souhaitez-vous utiliser une voie plutôt que l'autre? Et quels sont les avantages de l'utilisation d'interfaces sur les classes abstraites pour représenter les différents triangles? Même si nous compliqué la description d'une forme, en utilisant l'interface vs classe abstraite semblent encore l'équivalent.
Un élément essentiel à des interfaces est qu'il permet de définir des comportements qui peuvent être partagés entre les classes indépendantes. Donc une interface Pilotable serait présent dans les classes de l'Avion ainsi que des Oiseaux. Donc dans ce cas, il est clair qu'une approche de l'interface est préféré.
Aussi, à tirer parti de la confusion de l'interface de l'extension d'une autre interface:
Quand faut-il "EST-UN" de la relation être ignoré au moment de décider sur ce que devrait être une interface?
Prenez cet exemple: LIEN.
Pourquoi 'VeryBadVampire' être une classe et de "Vampire" être une interface? Un "VeryBadVampire" EST-UN "Vampire", si ma compréhension est qu'un "Vampire" doit être une super-classe (peut-être une classe abstraite). Un "Vampire" classe peut implémenter "Létales" à garder son létal de comportement. En outre, un "Vampire" EST-UN "Monstre", afin de "Monstre" devrait être une classe ainsi. Un "Vampire" classe peut implémenter une interface appelée "Dangereux" pour garder son comportement dangereux. Si nous voulons créer un nouveau monstre appelé "BigRat' qui est dangereux, mais ils ne sont pas mortels, alors nous pouvons créer un "BigRat' classe qui s'étend de "Monstre" et met en œuvre des "Dangereuses".
Ne serait pas au-dessus d'atteindre le même résultat que l'utilisation de "Vampire" comme une interface (décrit dans le lien)? La seule différence que je vois est que l'utilisation de l'héritage de classe et la préservation de l' "EST-UN" de la relation efface beaucoup de confusion. Pourtant, ce n'est pas suivie. Quel est l'avantage de faire cela?
Même si vous voulais un monstre à part vampirique comportement, il est toujours possible de redéfinir la façon dont les objets sont représentés. Si nous voulions un nouveau type de vampire, monstre appelé "VeryMildVampire" et nous avons voulu créer un vampire-comme monstre appelé "Chupacabra", nous pouvons le faire:
"Vampire" classe étend "Monstre" met en œuvre "Dangereux", "Létales", "BloodSuckable'
'VeryMildVampire' classe étend "Vampire" classe
'Chupacabra" class extends 'Monstre' implémente 'BloodSuckable'
Mais nous pouvons aussi le faire:
'VeryMildVampire" s'étend au "Monstre" met en œuvre Dangereux, Mortel, Vampirique
'Chupacabra" s'étend au "Monstre" met en œuvre Dangereux, Vampirique
La deuxième façon, ici, crée un " Vampirique de l'interface, de sorte que l'on peut le plus facilement définir une relative monstre plutôt que de créer un groupe d'interfaces qui définissent vampirique comportements (comme dans le premier exemple). Mais cela rompt la relation " EST-UN. Donc, je suis confus...
- Vous ai expliqué le problème avec beaucoup de clarté. Apprécier l'effort 🙂
Vous devez vous connecter pour publier un commentaire.
Rappelez-vous le concept de base lors de l'utilisation de classes abstraites et interfaces.
Les classes abstraites sont utilisés lors de la classe à l'étendue est plus étroitement couplée pour la classe de mise en oeuvre, j'.e lorsque les deux ont une relation parent-enfant.
Dans l'exemple:
Breed1
etBreed2
sont les deux types de chien et a certains comportement commun comme un chien.Considérant que, une interface est utilisée lors de l'implémentation de la classe a une fonction, il peut prendre à partir de la classe de mise en œuvre.
Tiger
etDog
sont deux catégories différentes, mais à la fois manger et faire des bruits ,qui sont différentes. De sorte qu'elles peuvent manger et le bruit deAnimal
.Utilisation d'une classe abstraite lorsque vous souhaitez effectuer une ou plusieurs méthodes abstraites.
Si vous voulez bien garder toutes abstrait, l'utilisation d'une interface.
C'est la question qui va venir lors de la conception des hiérarchies de classes qui sont peu compliqué que la normale. Mais en général, il ya quelques choses que vous devez savoir lors de l'utilisation de classes abstraites et les interfaces
Classe Abstraite
Interface
Généralement utiliser les Interfaces pour les " - " en mesure de l'alinéa(comme dans la fonctionnalité).
Par exemple:-
Runnable
Observable
Utilisation de classes abstraites pour quelque chose comme " est-un(évolution format).
Par exemple:-
Number
Graphics
Mais des règles strictes et rapides ne sont pas faciles à créer. Espérons que cela aide
Vous avez quelques questions ici. Mais je pense que, fondamentalement, vous posez des questions à propos de l'interface vs classe abstraite.
Avec les interfaces, vous pouvez avoir des classes qui implémentent des interfaces multiples. Cependant, l'interface n'est pas durable si vous souhaitez l'utiliser comme l'API. Une fois que l'interface est publié, il est difficile de modifier l'interface, car il va casser des autres codes.
Avec classe abstraite, vous pouvez uniquement s'étend sur une classe. Cependant, la classe abstraite est durable pour l'API parce que vous pouvez toujours modifier les versions ultérieures sans casser d'autres personnes de code. Aussi avec classe abstraite, vous pouvez avoir prédéfini de mise en œuvre. Par exemple, dans votre Triangle d'exemple, pour une classe abstraite, vous pouvez avoir une méthode countEdges() qui retourne 3 par défaut.
C'est une question qui revient très souvent, et pourtant il n'y a pas une seule "bonne" réponse qui va plaire à tout le monde.
Classes représentent est-un les relations et les interfaces représentent n' comportement. J'ai l'habitude de passer par quelques règles empiriques:
En outre, la plupart des exemples de formes et de personnes (ou les vampires d'ailleurs!) sont généralement pauvres des exemples du monde réel les modèles. La "bonne" réponse dépend de ce que votre application a besoin. Par exemple, vous avez mentionné:
Votre demande vraiment besoin de toutes ces interfaces? Combien de types différents de
Monster
s sont là? En effet, les classes autres queVampire
que de mettre en œuvreBloodSuckable
?Essayez de ne pas trop généraliser et d'en extraire des interfaces lorsque vous n'avez pas besoin pour eux. Cela remonte à la règle d'or: le bâton avec une simple classe, à moins que votre cas d'utilisation, les exigences d'une interface.
C'est une bonne question. Il y a beaucoup de bonnes et de mauvaises réponses à cette question. Typique de la question est, quelle est la différence entre une classe abstraite une interface? Permet de voir où vous utilisez les classes abstraites et où vous utilisez l'interface.
Où l'utilisation de classes abstraites:
En termes de programmation orientée objet, Si il y a une hiérarchie d'héritage, alors vous devriez utiliser une classe abstraite pour le modèle de votre conception.
Où à utiliser des interfaces:
Lorsque vous devez vous connecter différents contrats(non liées classes) à l'aide d'un contrat commun, alors vous devriez utiliser une interface. Permet de prendre de la Collection de cadre comme un exemple.
File d'attente,Liste,Ensemble ont des structures différentes de leur mise en œuvre.Mais encore ils ont en commun certaines de comportements (add(),remove(). Nous pouvons donc créer une interface appelée la Collecte et l', nous avons déclaré comportements communs dans l'interface. Comme vous le voyez, ArrayList met en œuvre tous les comportements à partir de les deux Liste et RandomAccess interfaces.Ce faisant, nous pouvons facilement ajouter de nouveaux contrats sans changer la logique existante. Cela s'appelle le "codage d'une interface".
Votre forme exemple est bon. Je regarde cela de cette façon:
Vous avez seulement les classes abstraites quand vous avez des méthodes ou des membres de variables qui sont partagées. Pour votre exemple pour
Shape
vous avez seulement un seul, jamais été appliquée la méthode. Dans ce cas, utilisez toujours une interface.Dire que vous avez un
Animal
classe. Chaque Animal garde une trace de la façon dont beaucoup de membres il est.Parce que nous avons besoin de garder une trace de la façon dont beaucoup de membres de chaque animal a, il est logique d'avoir la variable membre de la classe mère. Mais chaque animal a un autre type de bruit.
Nous avons donc besoin de faire une classe abstraite comme nous l'avons variables membres et mis en œuvre des méthodes ainsi que des méthodes abstraites.
Pour votre deuxième question, vous avez besoin de vous demander cela.
Est un Triangle va toujours être une forme?
Si oui, vous devez avoir Triangle étendre à partir de la Forme de l'interface.
Donc, en conclusion - avec votre première série d'exemples de code, choisissez l'interface. Avec le dernier set, cliquez sur le deuxième moyen.