2010-08-20 2 views
6

Donc, ceci est la question de l'héritage lancinante finale que j'ai eu pour un petit moment, donc je voulais aller de l'avant et demander. Je vais donner un exemple en PHP:Héritage sous le capot

<?php 

class Base 
{ 
    private $z = 4; 


    function GetPrivate() 
    { 
     echo $this->z; 
    } 

} 

class Derived extends Base 
{ 
} 

$b = new Base(); 
$d = new Derived(); 

$d->GetPrivate(); 

>

assez simple. Quand j'ai toujours lu sur l'héritage, l'explication était simplement "vous héritez du public et des membres protégés" et c'est tout. Ce que je ne comprends pas, c'est un certain nombre de choses sur la façon dont l'interprète dans cet exemple détermine ce qui appartient à quoi. Par exemple, lorsque je crée une classe dérivée, je peux utiliser la fonction publique "GetPrivate" de la base pour obtenir les variables privées de la classe de base. Cependant, la définition simple de l'héritage ne fonctionne pas avec moi. Ce que je veux dire, c'est que j'hérite de la méthode GetPrivate mais j'ai toujours un lien vers des variables privées issues de cette méthode qui appartenait à la classe de base (même si $ this fait référence à l'objet de classe dérivé). Je ne pouvais pas créer une nouvelle fonction dans la classe Derived pour accéder à ces variables privées.

Ainsi, l'interpréteur garde-t-il un œil sur les fonctions héritées de la classe de base et les liens possibles qu'elles contiennent pour les membres privés uniquement disponibles pour cette classe de base?

Répondre

2

L'interpréteur (ou le compilateur dans un autre langage OOP), vérifie l'accès une étape à la fois.

Lorsque vous appelez $d->GetPrivate();, l'interprète vérifier le contexte dans c'est le principal (contexte public que je suppose que vous n'êtes pas dans une classe liée à Drerived ou Base) et GetPrivate() est une méthode publique. Ainsi, $d->GetPrivate(); est autorisé dans ce contexte donc pas d'erreur.

Dans GetPrivate(), le contexte est objet $d comme Base et l'accès à z est un élément privé de l'objet courant ($d). Ainsi, l'accès est valide.

Le concept qui intervient ici est 'Data Hiding' (contrôle d'accès) et 'Encapsulation' (combinaison de données et fonction).

L'héritage de jouer seulement permet à GetPrivate() de Base d'être utilisé comme appartenant à un objet de Derived.

Il est vrai qu'il existe toujours un lien vers une donnée privée mais ce lien n'est pas direct. L'importance est que l'accès se passe comme Base classe autorisée.

Donc, pour répondre à votre question est:

OUI! L'interpréteur garde un œil sur les fonctions héritées de la classe de base et les liens possibles qu'elles contiennent avec les membres privés uniquement disponibles pour cette classe de base.

Espérons que cela aide.

2

La réponse est un oui, essayez ceci:

<?php 


class Base 
{ 
    private $z = 10; 

    public function getPrivate() 
    { 
     return $this->z; 
    } 
} 


class Derived extends Base 
{ 
    public function getPrivate() 
    { 
     return $this->z; 
    } 
} 

$a = new Derived(); 

echo $a->getPrivate(); 

Vous verrez que maintenant que nous avons défini getPrivate sur l'accès nous ne pouvons classe Derived plus z dans le Base depuis son privé, si nous voulons être en mesure d'y accéder à partir de la classe dérivée dont nous avons besoin de déclarer qu'il est protégé au lieu de privé.

1

Eh bien, je ne peux pas dire grand-chose au sujet des détails de l'analyseur, mais la clé de la compréhension est à comprendre ce que signifie visibility:

membres de la classe déclarées publiques est accessible partout. Les membres déclarés protégés ne peuvent être accédés que dans la classe elle-même et par les classes héritées et parentes. Les membres déclarés comme privés ne peuvent être accédés que par la classe qui a défini le membre.

Now, the PHP manual also states:

Par exemple, lorsque vous étendez une classe, la sous-classe hérite de toutes les méthodes publiques et protégées de la classe parente. À moins qu'une classe ne remplace ces méthodes, elles conservent leur fonctionnalité d'origine.

Si vous faites un var_dump($d) sur la classe dérivée, vous verrez qu'il contient Base->z:

object(Derived)#2 (1) { 
    ["z":"Base":private]=> 
    int(4) 
} 

Donc, il y a une référence à z dans la base, mais il est privé et comme moyen privé le membre ne peut être accessible par la classe qui définit le membre, vous ne pouvez pas y accéder à partir de Derived.

En offrant des méthodes publiques dans Base pour accéder au membre privé, vous contrôlez effectivement l'accès via la méthode parent. Peut-être $z est quelque chose qui doit être en lecture seule dans les classes étendues, par exemple un adaptateur de base de données.

Ceci est la dissimulation d'informations et le contrôle d'accès. Cela ne signifie pas, si vous étendez Base, vous perdrez $ z. Héritage est une relation is-a. Dérivé is-a Base et en tant que tel, il a un $ z, mais pas sur lui-même, mais à travers son parent.

Questions connexes