Saat Anda mendeklarasikan variabel instan dari kelas privat, Anda tidak dapat mengaksesnya di kelas lain jika Anda mencoba melakukannya, kesalahan waktu kompilasi akan dihasilkan
Tapi, jika Anda mewarisi kelas yang memiliki bidang pribadi, termasuk semua anggota kelas lainnya, variabel pribadi juga diwariskan dan tersedia untuk subkelas.
Tapi, Anda tidak dapat mengaksesnya secara langsung, jika Anda melakukannya kesalahan waktu kompilasi akan dihasilkan
Contoh
Demo Langsung
class Person{ private String name; public Person(String name){ this.name = name; } public void displayPerson() { System.out.println("Data of the Person class: "); System.out.println("Name: "+this.name); } } public class Student extends Person { public Student(String name){ super(name); } public void displayStudent() { System.out.println("Data of the Student class: "); System.out.println("Name: "+super.name); } public static void main(String[] args) { Student std = new Student("Krishna"); } }Kesalahan waktu kompilasi
Student.java:17: error: name has private access in Person System.out.println("Name: "+super.name); ^ 1 error_Untuk mengakses anggota privat superclass, Anda perlu menggunakan metode setter dan getter dan memanggilnya menggunakan objek subclass
Anggota yang dideklarasikan dilindungi hanya dapat diakses di dalam kelas itu sendiri dan oleh kelas yang diwariskan dan kelas induk. Anggota yang dideklarasikan sebagai pribadi hanya dapat diakses oleh kelas yang mendefinisikan anggota tersebut
Ini benar-benar berfungsi. Yaitu jika saya mendeklarasikan sesuatu yang dilindungi atau pribadi, itu tidak dapat diakses dari sebuah instance (ala $a->prop; ). Dan ketika saya mendeklarasikan sesuatu sebagai pribadi, itu hanya dapat berada di dalam kelas itu sendiri dan, secara teoritis dan fungsional , tidak diteruskan ke ekstensi apa pun dari kelas root. Dalam praktiknya ini tampaknya berhasil. jika saya mendeklarasikan $prop sebagai private $this->prop tidak akan berfungsi di kelas anak (kecuali saya mendeklarasikan $prop private lain di dalam kelas anak itu).
Oke sekarang Anda mengatakan dengan baik jika Anda akan melakukannya lalu mengapa tidak membuat $prop protected alih-alih pribadi? . sekali lagi ini berfungsi, secara fungsional .
Pertanyaan saya adalah tentang sesuatu yang saya perhatikan melalui objek var_dumps
class Test1{ public $tesVar = 'Veronica'; public $hold = array(); protected $name = ''; public $another= 'other'; private $births = 'Test2'; private $OnlyHere = 'only once'; function Test1($name){ $this->name=$name; } function output (){ foreach ($this as $k=>$that){ echo $k,'=',$that,'<br>'; } if (isset($this->OnlyHere)) {echo $this->OnlyHere.'<br>';} else {echo "just chickens!";} echo '<b>I produce ', (($this->births) ?$this->births:'nothing'),'</b><br>' ; echo '-----<br>'; } function makeChild ($name="anonn"){ if($this->births) { $this->hold[$name]=new $this->births($name); return $this->hold[$name]; } return false; } } class Test2 extends Test1{ private $births = 'Test3'; } class Test3 extends Test2{ private $births = false;// neuters class } $Test1=new Test1('Start'); $Test1->tesVar="And Ray"; $Test1->makeChild("first"); $Test1->hold['first']->makeChild('second'); echo'<pre>'; $Test1->hold['first']->output(); var_dump($Test1);Ketika properti adalah PRIVATE, itu masih muncul di var_dump objek turunan, bahkan jika TIDAK dideklarasikan di kelas mereka (saya berharap ini untuk DILINDUNGI, tetapi tidak untuk PRIVATE). Ini adalah .. properti tidak dapat diakses .. tetapi TAMPAKNYA sudah disetel?. ?
Lebih aneh lagi, jika Anda mendeklarasikan kembali properti pribadi sehingga memiliki nilai yang berbeda… maka Anda memiliki GANDA instance dari properti yang sama (sekali lagi hanya yang baru saja dideklarasikan yang benar-benar dapat diakses dari kelas… tetapi masih aneh)
object(Test1)#1 (5) { ["tesVar"]=> string(7) "And Ray" ["hold"]=> array(1) { ["first"]=> object(Test2)#2 (6) { ["births:private"]=> string(5) "Test3" ["tesVar"]=> string(8) "Veronica" ["hold"]=> array(1) { ["second"]=> [I] object(Test2)#3 (6) { [B] ["births:private"]=> string(5) "Test3"[/B] ["tesVar"]=> string(8) "Veronica" ["hold"]=> array(1) { ["anonn"]=> object(Test2)#4 (6) { ["births:private"]=> string(5) "Test3" ["tesVar"]=> string(8) "Veronica" ["hold"]=> array(0) { } ["name:protected"]=> string(5) "anonn" ["another"]=> string(5) "other" [B] ["births:private"]=> string(5) "Test2"[/B] } }[/I] ["name:protected"]=> string(6) "second" ["another"]=> string(5) "other" ["births:private"]=> string(5) "Test2" } } ["name:protected"]=> string(5) "first" ["another"]=> string(5) "other" ["births:private"]=> string(5) "Test2" } } ["name:protected"]=> string(5) "Start" ["another"]=> string(5) "other" ["births:private"]=> string(5) "Test2" }'Semi-duplikasi' ini tidak terjadi jika properti disetel ke DILINDUNGI alih-alih PRIBADI, tetap saja tampaknya tidak masuk akal juga
JUGA
Dalam pengujian saya 'hanya sekali' tidak boleh digaungkan karena properti yang memuatnya adalah PRIVATE dan tidak diwarisi oleh kelas anak
Saya akan berharap, bahwa dalam objek apa pun, TETAPI salah satu kelas TEST1, isset( $this->OnlyHere) itu akan salah
Sebenarnya, ini bahkan lebih berbelit-belit dari itu. Apa yang tampaknya terjadi adalah FUNGSI YANG DIPEROLEH (output()), dieksekusi di kelas root dan bukan di kelas instance, dan dengan demikian mereka juga memiliki akses ke semua properti kelas root PRIVATE. Solusinya adalah dengan menulis ulang fungsi SAMA PERSIS dalam kelas anak pertama. Tapi bukankah itu meniadakan inti dari OOP?
Bisakah seseorang menjelaskan (disederhanakan) tentang hal ini?
Ini bekerja persis seperti yang seharusnya. Menyetel properti ke kehendak pribadi tidak menghentikannya untuk diwariskan. Itu masih dipakai dan diberi nilai oleh kelas root. Satu-satunya perbedaan antara private dan protected adalah apakah kelas anak memiliki akses langsung ke nilainya atau tidak. Dalam contoh Anda, fungsi output() menggemakan semua variabel dalam cakupannya
Misalnya, pikirkan tentang cara kerja fungsi get dan set. Mereka mengizinkan akses ke variabel anggota pribadi oleh seorang anak tanpa mengizinkan akses langsung ke nilai itu sendiri. Jika fungsi induk tidak memiliki akses ke nilai dalam cakupannya sendiri, maka tidak akan ada alasan keberadaannya
Misalnya
<?php class Test1 { private $name; public function __construct(){} public function set( $name ) { $this->name = $name; } public function getName() { return $this->name; } public function parentOutput() { echo $this->name . '<br />'; } } class Test2 extends Test1 { public function __construct( $name ) { $this->set( $name ); // works because it is a function defined in the parent and retains access to parent variable. } public function childOutput() { echo $this->name . '<br />'; // will no work because the value exists but is invisible in the current scope. } } $test = new Test2( 'John Doe' ); $test->parentOutput(); // will display the name $test->childOutput(); // will cause an error _Memanggil metode keluaran akan menampilkan nama karena fungsi tersebut dideklarasikan di kelas induk dan mempertahankan akses ke semua variabel anggota induk
Memanggil metode childOutput akan menimbulkan kesalahan karena dideklarasikan di kelas anak. Meskipun mewarisi variabel nama, ia tidak dapat melihatnya atau mengaksesnya tanpa menggunakan fungsi getName
Namun, jika kita menulis ulang childOutput berikut ini akan berhasil, karena fungsi getName mempertahankan akses ke variabel nama
public function childOutput() { echo $this->getName() . '<br />'; // value access through parent function }Apakah ini membantu sama sekali?
Ini berfungsi persis seperti yang seharusnya. Menyetel properti ke kehendak pribadi tidak menghentikannya untuk diwariskan. Satu-satunya perbedaan antara private dan protected adalah apakah kelas anak memiliki akses langsung ke nilainya atau tidak.
Itulah yang saya coba konfirmasi. Masuk akal bagi saya sejak awal, tetapi juga tampak 'boros' karena properti yang tidak dapat diakses masih disimpan di kelas anak (jika itu masuk akal)
Saya memiliki SATU PERTANYAAN yang tersisa, dan metode yang diwariskan tampaknya bertindak seolah-olah mereka berada di kelas induk (dan karena itu mereka memiliki akses ke properti atau nilai properti yang ditetapkan pada lingkup induk
Mungkin ini bukan tujuan pewarisan dan saya salah berpikir seperti ini.. yaitu bahwa metode pewarisan memiliki ruang lingkup saat ini, bukan ruang lingkup induk. Alasan saya merasa tidak praktis adalah karena (karena Anda pada dasarnya menggunakan ini dalam contoh Anda) variabel ajaib $this->… akan selalu menunjuk ke kelas dari mana metode tersebut diwariskan dan BUKAN kelas saat ini… kecuali metode tersebut disalin
Inilah yang saya maksud
class Test1 { private $name; private $value= 10; public function output() { echo $this->value . '<br />'; // } } class Test2 extends Test1 { private $value=5; // for the sake of example, lets say $value must be '5' anytime an intance of Test2 is dealt with. } $test = new Test2(); $test->output(); // will display the 'value' property of the class ; one would expect '10' if Test1, '5' if Test2. _Ini berfungsi, namun jika kita menulis ulang fungsi lagi di kelas anak (tentu saja hal itu mengalahkan upaya apa pun untuk berhemat kode dan membuat kode menjadi berlebihan)
class Test1 { private $name; private $value= 10; public function output() { echo $this->value . '<br />'; // } } class Test2 extends Test1 { private $value=5; public function output() { echo $this->value . '<br />'; // } } $test = new Test2(); $test->output(); // will display the 'value' property of the class ; one would expect '10' if Test1, '5' if Test2.Tampaknya perbaikan yang cukup sederhana untuk hanya membuat $value protected , bukan publik, tetapi bagaimana jika $value tidak seharusnya ada sama sekali di TEST 2?
class Test1 { private $name; private $value= 10; public function output() { echo $this->value . '<br />'; // } } class Test2 extends Test1 {} $test = new Test2(); $test->output(); _Saya masih menampilkan 1) dan menghapus $value di Test2 tidak akan membantu, karena fungsinya benar-benar berjalan di Test1 dan bekerja pada properti Test1, meskipun itu adalah turunan dari Test2. semoga pertanyaan saya masuk akal…
Jika Tes 2 seharusnya tidak memiliki $nilai, maka Anda tidak boleh mewarisi dari kelas yang berisi $nilai (mis. Tes1). Mewarisi berarti Anda mengambil semua metode dan variabel dari kelas yang Anda perluas. Anda harus menggunakan variabel pribadi karena metode di kelas yang diwariskan mungkin memerlukan penggunaan variabel pribadi tersebut
Sekarang ketika Anda mendefinisikan ulang output(), Anda benar-benar menimpa metode dasar untuk output di Test1, jadi ketika Anda memiliki instance Test2()->output() Anda menjalankan output yang ditentukan dalam Test2() alih-alih Test1()
Memperluas paling baik diringkas dengan contoh berikut (setidaknya itu selalu membantu saya
class Animal { private $fed = false; protected $type = "Unknown"; public function MakeNoise() { echo "No Noise Defined"; } public function GetType() { echo "Type of " . $this->type; } public function FeedMe() { $this->fed = true; } public function HasBeenFed() { return $this->fed; } } class Dog extends Animal { public function __construct() { $this->type = "Dog"; } public function MakeNoise() { echo "Woof Woof"; } } class Cat extends Animal { public function __construct() { $this->type = "Cat"; } public function MakeNoise() { echo "Meow Meow"; } } $dog = new Dog(); $dog->GetType(); // Type of Dog $dog->MakeNoise(); // Woof Woof $dog->HasBeenFed(); // false; $dog->FeedMe(); $dog->HasBeenFed(); // true; $cat = new Cat(); $cat->GetType(); // Type of Cat $cat->MakeNoise(); // Meow Meow $cat->HasBeenFed(); // false; $cat->FeedMe(); $cat->HasBeenFed(); // true; $animal = new Animal(); $animal->GetType(); // Type of Unknown $animal->MakeNoise(); // No Noise Defined $animal->HasBeenFed(); // false; $animal->FeedMe(); $animal->HasBeenFed(); // true; _Baik Anjing maupun Kucing, tidak dapat mengakses $this->fed, tetapi memanggil HasBeenFed dan FeedMe sama-sama membutuhkan dan memiliki akses ke $this->fed
Saya tidak pernah benar-benar memikirkannya seperti itu. Masalahnya dengan PHP adalah memungkinkan kita untuk lolos dengan banyak hal yang tidak dapat kita lakukan dengan bahasa yang diketik secara ketat
Saat mewarisi kelas, konstruktor induk harus selalu dipanggil secara eksplisit. Anak itu tidak secara ajaib mendapatkan akses ke metode di kelas induk. Pertama-tama harus membuat instance yang dapat diakses yang dapat digunakan. Jadi sungguh, meskipun metode orang tua dapat diakses oleh anak, mereka harus tetap beroperasi dalam ruang lingkupnya sendiri. Orang tua tidak tahu bahwa itu telah diwariskan atau diperpanjang dan bertindak seperti itu
Hal lain yang perlu diingat adalah Anda selalu dapat mengakses metode yang telah diganti menggunakan induknya. operator
<?php class Test1 { private $value = 10; public function __construct( $value ) { $this->value = $value; } public function output() { echo 'Test1\\'s value is ' . $this->value . '<br />'; // } } class Test2 extends Test1 { private $value = 5; public function __construct( $value ) { parent::__construct( $value ); $this->value = $value * 2; } public function output() { parent::output(); // outputs 5 echo 'Test2\\'s value is ' . $this->value . '<br />'; // outputs 10 } } $test = new Test2( 5 ); $test->output();Juga seperti yang dikatakan cpradio, jika Anda memperluas kelas yang memiliki nilai yang tidak Anda perlukan, maka arsitektur objek yang Anda gunakan harus dievaluasi ulang. Keindahan pemrograman adalah Anda dapat membuatnya bekerja dengan cara apa pun yang paling sesuai untuk Anda
Kasus untuk dan melawan pribadi vs dilindungi. http. //fabien. potensi. org/article/47/pragmatism-over-theory-protected-vs-private
Koreksi saya jika saya salah, tetapi bukankah inti dari artikel ini menyatakan bahwa seseorang yang sebelumnya tidak pernah menggunakan private untuk apa pun, sekarang melakukannya, dan mendukung sehingga membantu API-nya?
Mungkin, saya terlalu sering bekerja di API di mana Anda hanya memaparkan apa yang bermakna dan masuk akal dan tidak lebih. Saya terutama menulis komponen yang berinteraksi dengan pihak ketiga atau layanan dalam perusahaan lokal, jadi saya terus bertanya pada diri sendiri (apakah ini sesuatu yang ingin/perlu ditimpa seseorang?) Jika jawabannya tidak 100% ya, itu akan ditandai
Jadi apakah saya melewatkan sesuatu tentang mengapa dilindungi lebih dihargai daripada pribadi? . Beri saya skenario kasus nyata di mana Anda menggunakan metode pribadi (dan Anda tanpa ragu memutuskan itu tidak akan atau perlu diperpanjang) dan Anda harus mengubahnya ke dilindungi/publik
Beberapa jawaban dan keterlibatan diri hanya datang dengan mengulangi pertanyaan yang sama pada munculnya jawaban lain untuk memaksa analisis seluk-beluk pertanyaan awal.
Pada tingkat teknis "metode override" telah menjadi jawaban yang diperbolehkan karena warisan dan metode yang dilindungi. Pertanyaan yang lebih dalam adalah mengapa metode override dan mengotak-atik rantai pewarisan diperlukan dan apakah harus mengutak-atik adalah tanda masalah desain lain yang lebih dalam.
Banyak kekeruhan topik ini berasal dari kebingungan bahwa pewarisan (detail implementasi teknis) sama dengan prinsip substitusi polimorfisme/Liskov (detail komunikasi/antarmuka eksternal)
Pokoknya saya akan menunjukkan bahwa jawaban sebenarnya terletak di luar komunitas PHP karena memiliki kebiasaan mengulangi semua yang nenek moyang kita lakukan namun najis demi pengalaman diri terkadang tanpa sadar mengubah merek praktik buruk dengan nama baru yang keren. Ada beberapa dekade informasi dan pengalaman untuk dikumpulkan tentang topik ini