2017-11-08 67 views
15
class Person { 
    public $name; 
    private $age; //private access 
} 

class Employee extends Person{ 
    public $id; 
    public $salary; //class property 
} 

$emp = new Employee(); 
$emp->name="ABCD"; 
$emp->age = 30; 
$emp->id=101; 
$emp->salary=20000; 

echo "<br/> Name : ".$emp->name; 
echo "<br/> Age : ".$emp->age; 

Trong mã này, biến lớp con $emp có thể truy cập trực tiếp vào thành viên riêng của lớp cha Person. Đây có phải là vi phạm quy tắc truy cập riêng tư không?Quyền truy cập riêng trong kế thừa

Nó đưa ra lỗi khi sử dụng biến lớp cha, nhưng hoạt động với biến lớp con !! Bất cứ ai có thể giải thích lý do tại sao?

+0

Bạn sẽ thấy nó nếu bạn 'var_dump ($ emp)' ... '[ "tuổi": "Người": private] => NULL [ "tuổi"] => int (30) '... private' Person :: age' là NULL nhưng mới, public 'Employee :: age' được tạo và thiết lập là 30. – CD001

+0

Vì lý do an toàn, tôi không bao giờ trả lại các thuộc tính một cách trực tiếp. Thay vào đó, hãy tạo một phương thức nhổ chúng ra – Thielicious

Trả lời

18

TLDR;

$emp->age = 30 không gọi mẹ thành viên tin age, nó tạo mới tài sản đối tượng trẻ em age động.

Giải thích

Trông giống như một lỗi, phải không? Trước hết, chúng ta hãy bình luận viên riêng của cha mẹ ở tất cả:

<?php 

class Person { 
    // private $age; 
} 

class Employee extends Person { 
} 

$emp = new Employee(); 
$emp->age = 10; 
echo $emp->age . "\n"; 
//out: 10 

Trong dòng $emp->age = 10 chúng tôi tạo ra tài sản mới của $emp đối tượng có tên age và giao nó đánh giá cao 10.

Khi bạn xác định thành viên của cha mẹ của bạn như tư nhân, trẻ em không thấy thành viên này tại tất cả:

<?php 

class Person { 
    private $age; 

    function __construct() { 
     $this->age = 30; 
    } 

    public function printAge() 
    { 
     echo sprintf("Parent::age = %s\n", $this->age); 
    } 
} 

class Employee extends Person { 
    private $age; 

    function __construct() { 
     parent::__construct(); 
     $this->age = 10; 
    } 

    public function printAge() 
    { 
     echo sprintf("Employee::age = %s\n", $this->age); 
     parent::printAge(); 
    } 
} 

$emp = new Employee(); 
$emp->printAge(); 

//out: 
//Employee::age = 10 
//Parent::age = 30 
3

Bạn đang chỉ định $emp->age = 30; Từ đối tượng ($emp).

Bây giờ khi bạn đang cố gắng truy cập vào bất kỳ biến sử dụng đối tượng (mà không phải là biến thành viên), Nó sẽ cho phép truy cập và tạo phạm vi địa phương

Không phải là nó không được coi là biến thành viên của lớp cụ thể.

Vì vậy, ở đây trong ví dụ của bạn $emp->age trong đó tuổi không được coi là biến thể thành viên của bất kỳ lớp nào vì nó không được xác định trong đó.

Bạn sẽ nhận được ý tưởng rõ ràng hơn nếu bạn thử bất kỳ tên biến nào không phải là thành viên của bất kỳ lớp nào. Bạn cũng sẽ nhận được kết quả cho họ.

Ví dụ thử mã dưới đây:

$emp->age_tmp = 30; 

echo "<br/> Age : ".$emp->age_tmp; 

Vì vậy, vấn đề không phải là về phạm vi nhưng nó sẽ tạo ra bản sao khác cho biến đó. $emp->age không có bất kỳ mối liên hệ với Person lớp age

DEMO

1

Trong PHP, bạn có thể tạo các thuộc tính bất cứ nơi nào trong các mã. Biến "tuổi" không phải là của lớp cha. bạn có thể thử điều này nếu bạn muốn

<?php 

class Person { 
public $name = "Scare"; 
private $age = 30; //private access 
protected $gender = "Man"; 
} 

class Employee extends Person{ 
public $id = 20; 
public $salary; //class property 
} 

$emp = new Employee(); 
echo $emp->id; 
echo $emp->name; 
echo $emp->age; 
$emp->age = "10"; 
echo $emp->age; 
echo $emp->gender; 
?> 

Biến hiển thị thuộc về lớp nhân viên và là người địa phương.

2

Bạn có thể xác định $object = new stdClass(); và gán giá trị với cú pháp $object->field = "value";.

Nếu lớp học siêu có trường riêng tư. Trường đó KHÔNG tồn tại ở trẻ em. Trong mã của bạn Nhân viên không có độ tuổi trường. Và $emp->age = 42; là mã php hợp lệ.

Để giữ tuổi riêng tư trong Nhân viên, bạn cần đặt trường là bảo vệ. Các trường được bảo vệ có nghĩa là trường riêng tư cho lớp siêu và cũng dành cho trẻ em.

Trường riêng tư của những người không có mặt ở trẻ em.

OOP php visibility

+0

Trường _exists_ ở trẻ em ... nó không thể nhìn thấy hoặc truy cập được. Sự khác biệt đáng kể. – cHao

1

Bằng cách này, nếu bạn muốn sở hữu tư nhân $age không được tạo ra từ một thể hiện bạn cũng có thể làm điều này:

class Person { 
    public $name; 
    private $age; //private access 

    public function __set($age, $value) { 
     return false; 
    } 
} 

__set() là một phương pháp kỳ diệu mà tự động thiết lập một mới bất động sản. Trường hợp inthis nó sẽ không hoạt động khi $age được cố gắng được thiết lập.

Bây giờ hãy thử, gán giá trị cho $age.

3v4l.org

+1

Đây là một đề xuất rất có giá trị..Cảm ơn !! –

+0

Thay vì chỉ đơn giản là trả lại 'false', mặc dù (có thể để lại cho bạn một số khoảnh khắc đầu trầy xước thực sự sau này), bạn có thể muốn ném một ngoại lệ. – cHao

+0

Tất nhiên, nhưng tôi đã đưa ra một ý tưởng – Thielicious

Các vấn đề liên quan