Interfaces et classes internal
Par -Alexandre LEGOUT aka LAlex- le 17 décembre 2007, 13:04 - AS3 / Flex2 - Lien permanent
L'AS3 nous a amené les classes internes (mot-clé internal) qui nous permettent d'encapsuler un certain nombre de fonctionnalités dans une classe disponible uniquement à la classe publique qui l'utilise. Bien pratique, cela évite les classes trop longues, et grâce à l'héritage (une classe interne peut en étendre une autre), cela peut aussi éviter l'utilisation d'un trop grand nombre de if, et donc abaisser la complexité du code.
Cela peut aussi permettre de disposer d'une classe qui n'est pas instanciable depuis l'extérieur. Seulement, il peut parfois être utile d'accéder à une instance de ces classes, et là, la solution c'est tout simplement les interfaces...
Prenons l'exemple d'une liste de contacts (VoIP un jour, VoIP toujours!), dans laquelle on peut sélectionner un contact. Le XML sera utilisé pour remplir cette liste, et un certain nombre d'actions peuvent être effectuées sur les contacts, mais la liste reste le seul moyen d'avoir des contacts: en gros, il est impossible de créer un contact via un constructeur de type new Contact(...).
L'utilisation conjointe des classes internes et des interfaces nous donnerai ceci: Une interface contact
package {
/**
* Contact public interface
*
* @author LAlex
*/
public interface Contact {
function sendMail(text:String) : void;
function get firstName() : String;
function get lastName() : String;
}
}
Une classe ContactList et son implémentation de l'interface en tant que classe interne
package {
/**
* @author LAlex
*/
public class ContactList {
private var _contacts:Array = [];
private var _selectedContactPosition : int = -1;
function ContactList(dP:XML = null) {
if (dP != null) {
setDataProvider(dP);
}
}
// Methods
public function setDataProvider(x : XML) : void {
for each (var contactNode:XML in x.contacts.contact) {
_contacts.push(new ContactImpl(contactNode));
}
}
public function selectContactAt(ind : int = -1) : void {
if (ind < _contacts.length) {
_selectedContactPosition = ind;
}
}
public function get selectedContact() : Contact {
if (_selectedContactPosition != -1) {
return _contacts[_selectedContactPosition] as Contact;
}
return null;
}
}
}
// Contact interface implementation
internal class ContactImpl
implements Contact {
private var _firstName:String;
private var _lastName:String;
function ContactImpl(x : XML) {
_firstName = x.@first;
_lastName = x.@last;
// Other initiation
}
public function sendMail(text : String) : void {
// Mail sending implementation
}
public function get firstName() : String {
return _firstName;
}
public function get lastName() : String {
return _lastName;
}
}
L'utilisation de cette classe donnerait:
var list : ContactList = new ContactList(<dataprovider><contacts><contact first="Alexandre" last="LEGOUT" /><contact first="Gérard" last="DUPONT" /></contacts></dataprovider>);
list.selectContactAt(1);
var selected : Contact = list.selectedContact;
trace(selected.firstName + " " + selected.lastName);
Et voilà, on a accès depuis l'extérieur de la classe à tous les
comportements "publics" d'un contact, sans avoir accés à son implémentation!
![]()
Alors je sais que c'est justement le but des interfaces, mais j'ai trouvé cette
utilisation intéressante, et assez représentative de l'utilité des interfaces,
au cas où vous ne seriez pas encore convaincus... ![]()
Commentaires
Fil des commentaires de ce billet