| 
          
           
 
 
          
          
           
            L’héritage est une forme de réutilisation du code qui permet aux programmeurs de développer de nouvelles classes à partir de classes existantes. Les classes existantes sont alors fréquemment appelées
            
             classes de base
            
            ou
            
             superclasses
            
            , alors que les nouvelles classes sont généralement appelées
            
             sous-classes
            
            . L’un des principaux avantages de l’héritage est qu’il permet de réutiliser le code d’une classe de base sans modifier le code existant. De plus, l’héritage ne nécessite pas de modifier les modes d’interaction des autres classes avec la classe de base. Plutôt que de modifier une classe existante, qui est peut-être soigneusement testée et déjà utilisée, l’héritage permet de traiter cette classe comme un module intégré qui peut être étendu à l’aide de propriétés et de méthodes supplémentaires. C’est pourquoi on utilise le mot-clé
            
             extends
            
            pour indiquer qu’une classe hérite d’une autre classe.
            
           
            L’héritage permet également de tirer parti du
            
             polymorphisme
            
            du code. Le polymorphisme est la possibilité d’utiliser un nom de méthode unique pour une méthode qui se comporte différemment en fonction des types de données qu’elle reçoit. Par exemple, supposons une classe de base appelée Shape, avec deux sous-classes appelées Circle et Square. La classe Shape définit une méthode appelée
            
             area()
            
            qui renvoie la surface de Shape. Si vous avez implémenté le polymorphisme, vous pouvez appeler la méthode
            
             area()
            
            pour les objets de type Circle ou Square et lui faire exécuter le calcul correct. L’héritage autorise le polymorphisme en permettant aux sous-classes d’hériter et de définir, ou
            
             override
            
            , les méthodes de la classe de base. Dans l’exemple suivant, la méthode
            
             area()
            
            est redéfinie par les classes Circle et Square :
            
           class Shape 
{ 
    public function area():Number 
    { 
        return NaN; 
    } 
} 
 
class Circle extends Shape 
{ 
    private var radius:Number = 1; 
    override public function area():Number 
    { 
        return (Math.PI * (radius * radius)); 
    } 
} 
 
class Square extends Shape 
{ 
    private var side:Number = 1; 
    override public function area():Number 
    { 
        return (side * side); 
    } 
} 
 
var cir:Circle = new Circle(); 
trace(cir.area()); // output: 3.141592653589793 
var sq:Square = new Square(); 
trace(sq.area()); // output: 1
           
            Dans la mesure où chaque classe définit un type de données, l’utilisation de l’héritage crée un rapport spécial entre une classe de base et une classe qui l’étend. Une sous-classe possède obligatoirement toutes les propriétés de sa classe de base, ce qui signifie qu’il est toujours possible de substituer une occurrence d’une sous-classe à une occurrence de la classe de base. Par exemple, si une méthode définit un paramètre du type Shape, il est parfaitement valable de lui transmettre un argument du type Circle, car Circle étend Shape, comme on peut le voir ci-dessous :
            
           function draw(shapeToDraw:Shape) {} 
 
var myCircle:Circle = new Circle(); 
draw(myCircle);
           
           
          
           
            
           
           
            Propriétés et héritage des occurrences
           
           
            
             Qu’elle soit définie à l’aide du mot-clé
             
              function
             
             ,
             
              var
             
             ou
             
              const
             
             , une propriété d’occurrence est héritée par toutes les sous-classes tant que cette propriété n’est pas déclarée avec l’attribut
             
              private
             
             dans la classe de base. Par exemple, la classe Event d’ActionScript 3.0 possède des sous-classes nombreuses qui héritent de propriétés communes à tous les objets événements.
             
            
             Pour certains types d’événements, la classe Event contient toutes les propriétés nécessaires pour définir l’événement. Ces types d’événements ne nécessitent pas de propriétés d’occurrence au-delà de celles qui sont définies dans la classe Event. L’événement
             
              complete
             
             , qui est déclenché lorsque des données ont été chargées avec succès, et l’événement
             
              connect
             
             , qui se produit lorsqu’une connexion réseau a été établie, sont des exemples de ce type d’événement.
             
            
             L’exemple suivant est extrait de la classe Event. Il montre certaines propriétés et méthodes dont les sous-classes héritent. Comme elles sont héritées, ces propriétés sont accessibles par une occurrence de n’importe quelle sous-classe.
             
            public class Event 
{ 
    public function get type():String; 
    public function get bubbles():Boolean; 
    ... 
 
    public function stopPropagation():void {} 
    public function stopImmediatePropagation():void {} 
    public function preventDefault():void {} 
    public function isDefaultPrevented():Boolean {} 
    ... 
}
            
             D’autres types d’événements nécessitent des propriétés uniques qui ne sont pas disponibles dans la classe Event. Ces événements sont définis à l’aide de sous-classes de la classe Event, ce qui permet d’ajouter de nouvelles propriétés à celles de cette classe Event. La classe MouseEvent est un exemple de sous-classe de ce type. Elle ajoute des propriétés uniques aux événements associés à un mouvement ou à un clic de souris, tels que les événements
             
              mouseMove
             
             et
             
              click
             
             . L’exemple suivant est extrait de la classe MouseEvent. Il montre la définition des propriétés inhérentes à la sous-classe parce qu’absentes de la classe de base.
             
            public class MouseEvent extends Event 
{ 
    public static const CLICK:String= "click"; 
    public static const MOUSE_MOVE:String = "mouseMove"; 
    ... 
 
    public function get stageX():Number {} 
    public function get stageY():Number {} 
    ... 
}
            
             
              Spécificateurs de contrôle d’accès et héritage
             
             
              Si une propriété est déclarée avec le mot-clé
              
               public
              
              , elle est visible de n’importe quel point du code. Cela signifie que le mot-clé
              
               public
              
              n’introduit aucune restriction sur l’héritage des propriétés, contrairement aux mots-clés
              
               private
              
              ,
              
               protected
              
              et
              
               internal
              
              .
              
             
              Si une propriété est déclarée avec le mot-clé
              
               private
              
              , elle n’est visible qu’à partir de la classe qui la définit. Autrement dit les sous-classes n’en héritent pas. Ce comportement est différent de celui des versions antérieures d’ActionScript où le mot-clé
              
               private
              
              se comportait plutôt comme le mot-clé
              
               protected
              
              d’ActionScript 3.0.
              
             
              Le mot-clé
              
               protected
              
              indique qu’une propriété est visible non seulement à partir de la classe qui la définit, mais aussi à partir de toutes les sous-classes de celle-ci. Contrairement au mot-clé
              
               protected
              
              en Java, en ActionScript 3.0 le mot-clé
              
               protected
              
              ne rend pas une propriété visible à partir de toutes les autres classes du même package. En ActionScript 3.0, seules les 
sous-classes peuvent accéder à une propriété déclarée avec le mot-clé
              
               protected
              
              . De plus, une propriété protégée est visible à partir d’une sous-classe même si celle-ci ne se trouve pas dans le même package que sa classe de base.
              
             
              Pour limiter la visibilité d’une propriété au package dans lequel elle est définie, vous pouvez soit utiliser le mot-clé
              
               internal
              
              , soit n’utiliser aucun spécificateur de contrôle d’accès. Le spécificateur de contrôle d’accès
              
               internal
              
              est appliqué par défaut si vous n’en indiquez aucun. Seule une sous-classe résidant dans le même package pourra hériter d’une propriété marquée comme internal. Seule une sous-classe résidant dans le même package peut hériter d’une propriété désignée comme
              
               internal
              
              .
              
             
              L’exemple suivant montre comment chaque spécificateur de contrôle d’accès affecte l’héritage dans et au-delà des package.  Le code ci-dessous définit une classe principale d’application appelée AccessControl et deux autres classes, Base et Extender. La classe Base se trouve dans un package appelé foo et la classe Extender, qui est une sous-classe de la classe Base, dans un package appelé bar. La classe AccessControl n’importe que la classe Extender et crée une occurrence de celle-ci qui tente d’accéder à une variable appelée
              
               str
              
              , définie dans la classe Base. La variable
              
               str
              
              est déclarée comme
              
               public
              
              , si bien que le code est compilé et exécuté comme l’illustre l’exemple ci-dessous :
              
             // Base.as in a folder named foo 
package foo 
{ 
    public class Base 
    { 
        public var str:String = "hello"; // change public on this line 
    } 
} 
 
// Extender.as in a folder named bar 
package bar 
{ 
    import foo.Base; 
    public class Extender extends Base 
    { 
        public function getString():String { 
            return str; 
        } 
    } 
} 
 
// main application class in file named AccessControl.as 
package 
{ 
    import flash.display.MovieClip; 
    import bar.Extender; 
    public class AccessControl extends MovieClip 
    { 
        public function AccessControl() 
        { 
            var myExt:Extender = new Extender(); 
            trace(myExt.str);// error if str is not public 
            trace(myExt.getString()); // error if str is private or internal 
        } 
    } 
}
             
              Pour voir l’effet des autres spécificateurs de contrôle d’accès lors de la compilation et de l’exécution de cet exemple, changez le spécificateur de contrôle de la variable
              
               str
              
              à
              
               private
              
              ,
              
               protected
              
              ou
              
               internal
              
              après avoir supprimé ou mis en commentaire la ligne suivante dans la classe
              
               AccessControl
              
              :
              
             trace(myExt.str);// error if str is not public 
             
            
             
              Redéfinition des variables impossible
             
             
              Les propriétés déclarées à l’aide des mots-clés
              
               var
              
              ou
              
               const
              
              sont héritées mais ne peuvent pas être redéfinies. Redéfinir, ou forcer, une propriété au sens de « override » signifie redéfinir cette propriété dans une sous-classe. Les accesseurs get et set (c’est-à-dire les propriétés déclarées avec le mot-clé
              
               function
              
              ) constituent le seul type de propriété qu’il est possible de redéfinir. Bien qu’il soit impossible de redéfinir une variable d’occurrence, vous pouvez obtenir le même résultat par la création des méthodes de lecture et de définition pour cette variable d’occurrence et en forçant ces méthodes.
              
             
            
           
          
           
            
           
           
            Redéfinition des méthodes
           
           
            
             Redéfinir une méthode signifie redéfinir le comportement d’une méthode héritée. Les méthodes statiques ne sont pas héritées et ne peuvent donc pas être redéfinies. Toutefois, les sous-classes héritent des méthodes d’occurrence et il est donc possible de redéfinir celles-ci sous réserve de deux conditions :
             
            
             - 
              
               La méthode d’occurrence ne doit pas être déclarée avec le mot-clé
               
                final
               
               dans la classe de base. Lorsqu’il est utilisé avec une méthode d’occurrence, le mot-clé
               
                final
               
               indique que le programmeur veut empêcher les sous-classes de redéfinir cette méthode.
               
              
             - 
              
               La méthode d’occurrence ne doit pas être déclarée avec le contrôle d’accès
               
                private
               
               dans la classe de base. Si une méthode est désignée comme
               
                private
               
               dans la classe de base, il est inutile d’utiliser le mot-clé
               
                override
               
               lors de la définition d’une méthode portant le même nom dans la sous-classe, puisque la méthode de la classe de base n’est pas visible à partir de la sous-classe.
               
              
               Pour redéfinir une méthode d’occurrence correspondant à ces critères, la définition de la méthode dans la sous-classe doit utiliser le mot-clé
               
                override
               
               et correspondre, comme défini ci-dessous, à la version de cette méthode dans la superclasse :
               
              
             - 
              
               La méthode de redéfinition doit avoir le même niveau de contrôle d’accès que celle de la classe de base.  Les méthodes définies comme internes doivent avoir le même niveau de contrôle d’accès que celles qui n’ont pas de spécificateur de contrôle d’accès.
               
              
             - 
              
               La méthode de redéfinition doit avoir le même nombre de paramètres que celle de la classe de base.
               
              
             - 
              
               Les paramètres de la méthode de redéfinition doivent avoir les mêmes annotations de type de données que ceux de la méthode de la classe de base.
               
              
             - 
              
               La méthode de redéfinition doit avoir le même type de renvoi que celle de la classe de base.
               
              
             
            
             Toutefois, il n’est pas nécessaire que les noms des paramètres de la méthode de redéfinition correspondent à ceux des paramètres de la classe de base, tant qu’il y a une correspondance entre le nombre de paramètres et leurs types de données.
             
            
             
              Instruction super
             
             
              Il arrive fréquemment que les programmeurs souhaitent compléter le comportement de la méthode de superclasse qu’ils redéfinissent, plutôt que de remplacer ce comportement. Il est donc nécessaire de disposer d’un mécanisme permettant à une méthode d’une sous-classe d’appeler sa propre superclasse. Ce mécanisme est assuré par l’instruction
              
               super
              
              qui contient une référence à la superclasse immédiate. L’exemple suivant définit une classe appelée Base, qui contient la méthode appelée
              
               thanks()
              
              et une sous-classe de Base appelée Extender, qui redéfinit la méthode
              
               thanks()
              
              . La méthode
              
               Extender.thanks()
              
              utilise l’instruction
              
               super
              
              pour appeler
              
               Base.thanks()
              
              .
              
             package { 
    import flash.display.MovieClip; 
    public class SuperExample extends MovieClip 
    { 
        public function SuperExample() 
        { 
            var myExt:Extender = new Extender() 
            trace(myExt.thanks()); // output: Mahalo nui loa 
        } 
    } 
} 
 
class Base { 
    public function thanks():String 
    { 
        return "Mahalo"; 
    } 
} 
 
class Extender extends Base 
{ 
    override public function thanks():String 
    { 
        return super.thanks() + " nui loa"; 
    } 
}
             
            
             
              Redéfinition des accesseurs Get et Set
             
             
              Bien qu’il soit impossible de redéfinir les variables définies dans une superclasse, il est possible de redéfinir les accesseurs Get et Set. Par exemple, le code suivant redéfinit un accesseur Get appelé
              
               currentLabel
              
              qui est défini dans la classe MovieClip d’ActionScript 3.0 :
              
             package 
{ 
    import flash.display.MovieClip; 
    public class OverrideExample extends MovieClip 
    { 
        public function OverrideExample() 
        { 
            trace(currentLabel) 
        } 
        override public function get currentLabel():String 
        { 
            var str:String = "Override: "; 
            str += super.currentLabel; 
            return str; 
        } 
    } 
}
             
              Le résultat de l’instruction
              
               trace()
              
              dans le constructeur de la classe OverrideExample est
              
               Override: null
              
              , ce qui montre que cet exemple a réussi à redéfinir la propriété héritée
              
               currentLabel
              
              .
              
             
            
           
          
           
            
           
           
            Propriétés statiques non héritées
           
           
            
             Les sous-classes n’héritent pas des propriétés statiques. Ces dernières ne sont donc pas accessibles par une occurrence d’une sous-classe. Une propriété statique n’est accessible que par le biais de l’objet classe dans lequel elle est définie. Par exemple, le code suivant définit une classe de base appelée Base et une sous-classe appelée Extender, qui étend la classe Base. Une variable statique appelée
             
              test
             
             est définie dans la classe Base. Le code de l’extrait ci-dessous ne peut être compilé en mode strict et génère une erreur d’exécution en mode standard.
             
            package { 
    import flash.display.MovieClip; 
    public class StaticExample extends MovieClip 
    { 
        public function StaticExample() 
        { 
            var myExt:Extender = new Extender(); 
            trace(myExt.test);// error 
        } 
    } 
} 
 
class Base { 
    public static var test:String = "static"; 
} 
 
class Extender extends Base { }
            
             La seule façon d’accéder à la variable statique
             
              test
             
             est par l’objet classe, comme le montre le code suivant :
             
            Base.test; 
            
             Il est toutefois permis de définir une propriété d’occurrence ayant le même nom qu’une propriété statique. Cette propriété d’occurrence peut être définie dans la même classe que la propriété statique, ou dans une sous-classe. Par exemple, la classe Base de l’exemple précédent peut comporter une propriété d’occurrence appelée
             
              test
             
             . Le code suivant peut être compilé et exécuté normalement, car la classe Extender hérite de la propriété d’occurrence. Ce code peut aussi être compilé et exécuté normalement si la définition de la variable d’occurrence test est déplacée (mais non copiée) dans la classe Extender.
             
            package 
{ 
    import flash.display.MovieClip; 
    public class StaticExample extends MovieClip 
    { 
        public function StaticExample() 
        { 
            var myExt:Extender = new Extender(); 
            trace(myExt.test);// output: instance 
        } 
    } 
} 
 
class Base 
{ 
    public static var test:String = "static"; 
    public var test:String = "instance"; 
} 
 
class Extender extends Base {}
            
           
          
           
            
           
           
            Propriétés statiques et chaîne de portée
           
           
            
             Bien que les propriétés statiques ne soient pas héritées, elles figurent dans la chaîne de portée de la classe qui les définit ainsi que de toute sous-classe de celle-ci. C’est pourquoi on dit que les propriétés statiques sont
             
              dans la portée
             
             à la fois de la classe dans laquelle elles sont définies et des sous-classes de celle-ci. Cela signifie qu’une propriété statique est directement accessible à partir du corps de la classe qui la définit et de toute sous-classe de celle-ci.
             
            
             L’exemple suivant modifie les classes définies dans l’exemple précédent pour montrer que la variable statique
             
              test
             
             , définie dans la classe Base, est dans la portée de la classe Extender. Autrement dit, la classe Extender peut accéder à la variable statique
             
              test
             
             sans qu’il ne soit nécessaire de faire précéder le nom de celle-ci du nom de la classe qui définit
             
              test
             
             .
             
            package 
{ 
    import flash.display.MovieClip; 
    public class StaticExample extends MovieClip 
    { 
        public function StaticExample() 
        { 
            var myExt:Extender = new Extender(); 
        } 
    } 
} 
 
class Base { 
    public static var test:String = "static"; 
} 
 
class Extender extends Base 
{ 
    public function Extender() 
    { 
        trace(test); // output: static 
    } 
     
}
            
             Si une propriété d’occurrence est définie avec le même nom qu’une propriété statique de la même classe ou d’une superclasse, la propriété d’occurrence est prioritaire dans la chaîne de portée. On dit alors que la propriété d’occurrence
             
              fait de l’ombre
             
             à la propriété statique, ce qui signifie que la valeur de la propriété d’occurrence est utilisée à la place de celle de la propriété statique. Par exemple, le code ci-dessous montre que si la classe Extender définit une variable d’occurrence appelée
             
              test
             
             , l’instruction
             
              trace()
             
             utilise la valeur de la variable d’occurrence à la place de celle de la variable statique.
             
            package 
{ 
    import flash.display.MovieClip; 
    public class StaticExample extends MovieClip 
    { 
        public function StaticExample() 
        { 
            var myExt:Extender = new Extender(); 
        } 
    } 
} 
 
class Base 
{ 
    public static var test:String = "static"; 
} 
 
class Extender extends Base 
{ 
    public var test:String = "instance"; 
    public function Extender() 
    { 
        trace(test); // output: instance 
    } 
     
}
            
           
          
          
           
          
          
          
          | 
         
          | 
         
          
          |