โปรดอธิบายเมื่อฉันควรใช้ PHP interface
และเมื่อใดที่ฉันควรใช้abstract class
?
ฉันจะเปลี่ยนฉันabstract class
ในสระinterface
?
โปรดอธิบายเมื่อฉันควรใช้ PHP interface
และเมื่อใดที่ฉันควรใช้abstract class
?
ฉันจะเปลี่ยนฉันabstract class
ในสระinterface
?
คำตอบ:
ใช้อินเทอร์เฟซเมื่อคุณต้องการบังคับให้นักพัฒนาทำงานในระบบของคุณ (รวมอยู่ในตัวคุณเอง) เพื่อใช้เมธอดจำนวนชุดบนคลาสที่พวกเขาจะสร้าง
ใช้คลาสนามธรรมเมื่อคุณต้องการบังคับให้นักพัฒนาทำงานในระบบของคุณ (รวมอยู่ในตัวคุณเอง) เพื่อใช้เมธอดจำนวนชุดและคุณต้องการให้วิธีการพื้นฐานบางอย่างที่จะช่วยให้พวกเขาพัฒนาคลาสลูกของพวกเขา
สิ่งที่ควรทราบอีกอย่างคือคลาสไคลเอ็นต์สามารถขยายคลาสนามธรรมได้เพียงคลาสเดียวเท่านั้นในขณะที่พวกเขาสามารถใช้หลายอินเตอร์เฟสได้ ดังนั้นถ้าคุณกำหนดสัญญาพฤติกรรมของคุณในคลาสนามธรรมนั่นหมายความว่าคลาสลูกแต่ละคลาสอาจเป็นไปตามสัญญาเดียวเท่านั้น บางครั้งสิ่งนี้เป็นสิ่งที่ดีเมื่อคุณต้องการบังคับให้ผู้ใช้โปรแกรมของคุณไปตามเส้นทางที่ต้องการ บางครั้งมันก็จะไม่ดี ลองคิดดูว่าอินเทอร์เฟซที่นับได้และ Iterator ของ PHP เป็นคลาสนามธรรมแทนอินเทอร์เฟซ
วิธีการหนึ่งที่ใช้กันทั่วไปเมื่อคุณไม่แน่ใจว่าจะไปทางไหน (ดังที่กล่าวไว้โดยcletus ด้านล่าง ) คือการสร้างอินเทอร์เฟซจากนั้นให้คลาสนามธรรมของคุณใช้อินเทอร์เฟซนั้น
ความแตกต่างระหว่างAbstract Class
และInterface
:
คลาสนามธรรม
ระดับนามธรรมสามารถให้การทำงานบางอย่างและออกจากส่วนที่เหลือสำหรับชั้นเรียนมา
ชั้นที่ได้รับอาจหรือไม่อาจแทนที่ฟังก์ชั่นคอนกรีตที่กำหนดไว้ในชั้นฐาน
คลาสเด็กที่ขยายจากคลาสนามธรรมควรมีความสัมพันธ์เชิงเหตุผล
อินเตอร์เฟซ
อินเตอร์เฟซที่ไม่สามารถมีฟังก์ชันการทำงานใด ๆ มันเพียง แต่มีคำจำกัดความของวิธีการ
คลาสที่ได้รับจะต้องให้สำหรับทุกวิธีการที่กำหนดไว้ในอินเตอร์เฟซ
คลาสที่แตกต่างและไม่เกี่ยวข้องทั้งหมดสามารถจัดกลุ่มอย่างมีเหตุผลด้วยกันโดยใช้อินเตอร์เฟส
abstract class X implements Y
และ class X implements Y
?
abstract class X implements Y
คุณประกาศว่าฟังก์ชันจำนวนมากของ X ควรนำมาใช้ในคลาสที่ได้รับและว่าทั้งนามธรรมและคลาสที่ได้มาจะต้องมีฟังก์ชั่นที่กำหนดไว้ใน Y ในขณะที่class X implements Y
หมายถึงเฉพาะที่คลาส X จะต้องมีฟังก์ชั่นที่กำหนดไว้ใน Y. ไม่ได้มีวัตถุประสงค์เพื่อนำไปใช้งานโดยคลาสอื่นที่ไม่ใช่ XI จริง ๆ แล้วจะข้ามการกำหนด Y เป็นอินเทอร์เฟซและใช้เฉพาะฟังก์ชันใน Y เป็นฟังก์ชันนามธรรมสาธารณะ / ป้องกัน / ส่วนตัวเพื่อให้แน่ใจว่าพวกเขาถูกนำมาใช้ในชั้นเรียน
ทำไมต้องใช้คลาสนามธรรม? ต่อไปนี้เป็นตัวอย่างง่ายๆ ช่วยบอกว่าเรามีรหัสต่อไปนี้:
<?php
class Fruit {
private $color;
public function eat() {
// chew
}
public function setColor($c) {
$this->color = $c;
}
}
class Apple extends Fruit {
public function eat() {
// chew until core
}
}
class Orange extends Fruit {
public function eat() {
// peeling
// chew
}
}
ตอนนี้ฉันให้แอปเปิ้ลแก่คุณแล้วคุณก็กินมัน มันรสชาติอะไร มันมีรสชาติเหมือนแอปเปิ้ล
<?php
$apple = new Apple();
$apple->eat();
// Now I give you a fruit.
$fruit = new Fruit();
$fruit->eat();
รสชาตินั้นเป็นอย่างไร มันไม่สมเหตุสมผลนักดังนั้นคุณไม่ควรทำเช่นนั้น นี่คือความสำเร็จโดยการทำให้นามธรรมระดับผลไม้เช่นเดียวกับวิธีการกินภายในของมัน
<?php
abstract class Fruit {
private $color;
abstract public function eat(){}
public function setColor($c) {
$this->color = $c;
}
}
?>
คลาสนามธรรมเหมือนกับอินเทอร์เฟซ แต่คุณสามารถกำหนดวิธีการในคลาสนามธรรมในอินเทอร์เฟซที่เป็นนามธรรมทั้งหมด คลาสนามธรรมสามารถมีทั้งวิธีที่ว่างเปล่าและวิธีการทำงาน / เป็นรูปธรรม ในอินเทอร์เฟซฟังก์ชั่นที่กำหนดไว้ไม่มีร่างกาย ในชั้นเรียนนามธรรมพวกเขาสามารถ
ตัวอย่างโลกแห่งความจริง:
<?php
abstract class person {
public $LastName;
public $FirstName;
public $BirthDate;
abstract protected function write_info();
}
final class employee extends person{
public $EmployeeNumber;
public $DateHired;
public function write_info(){
//sql codes here
echo "Writing ". $this->LastName . "'s info to emloyee dbase table <br>";
}
}
final class student extends person{
public $StudentNumber;
public $CourseName;
public function write_info(){
//sql codes here
echo "Writing ". $this->LastName . "'s info to student dbase table <br>";
}
}
///----------
$personA = new employee;
$personB = new student;
$personA->FirstName="Joe";
$personA->LastName="Sbody";
$personB->FirstName="Ben";
$personB->LastName="Dover";
$personA->write_info();
// Writing Sbody's info to emloyee dbase table
$personB->write_info();
// Writing Dover's info to student dbase table
What does that taste like? Well, it doesn't make much sense, so you shouldn't be able to do that.
ตอนนี้ฉันรู้ว่าเป็นนามธรรม!
final
คำหลักทำอย่างไร โพสต์ที่ดีขอบคุณ
แนวปฏิบัติที่เหมาะสมที่สุดคือการใช้อินเทอร์เฟซเพื่อระบุสัญญาและคลาสนามธรรมเป็นเพียงการนำไปใช้งาน คลาสนามธรรมนั้นสามารถเติมข้อมูลสำเร็จรูปจำนวนมากเพื่อให้คุณสามารถสร้างการใช้งานโดยเพียงแค่เอาชนะสิ่งที่คุณต้องการหรือต้องการโดยไม่บังคับให้คุณใช้การใช้งานเฉพาะ
เพียงโยนสิ่งนี้ลงในส่วนผสม แต่ตามที่ Cletus พูดถึงโดยใช้อินเทอร์เฟซร่วมกับคลาสนามธรรมฉันมักจะใช้อินเทอร์เฟซเพื่ออธิบายแนวคิดการออกแบบของฉัน
ตัวอย่างเช่น
<?php
class parser implements parserDecoratorPattern {
//...
}
ด้วยวิธีนี้ทุกคนที่อ่านโค้ดของฉัน (และใครจะรู้ว่ารูปแบบของมัณฑนากรคืออะไร) จะรู้ได้ทันที) ฉันจะสร้างตัวแยกวิเคราะห์และ b) ได้อย่างไรเพื่อดูว่าวิธีการใดที่ใช้ในการปรับใช้
นอกจากนี้และฉันอาจออกจากฐานที่นี่ไม่ได้เป็นโปรแกรมเมอร์ Java / C ++ / etc แต่ประเภทข้อมูลสามารถเข้ามาเล่นที่นี่ วัตถุของคุณเป็นประเภทและเมื่อคุณผ่านวัตถุประเภทนั้นโดยทางโปรแกรม การย้ายไอเท็มที่สามารถหดได้ของคุณลงในอินเตอร์เฟสจะเป็นตัวกำหนดประเภทที่เมธอดส่งคืน แต่ไม่ใช่ประเภทพื้นฐานของคลาสที่ใช้มัน
ช้าและฉันไม่สามารถนึกถึงตัวอย่างรหัส psudo ที่ดีกว่าได้
<?php
interface TelevisionControls {};
class Remote implements TelevisionControls {};
class Spouse implements TelevisionControls {};
Spouse spouse = new Spouse();
Remote remote = new Remote();
isSameType = (bool)(remote == spouse)
ความแตกต่างที่สำคัญคือคลาสนามธรรมสามารถมีการใช้งานเริ่มต้นในขณะที่อินเตอร์เฟซไม่สามารถ
อินเทอร์เฟซคือสัญญาของพฤติกรรมโดยไม่มีการใช้งานใด ๆ
นอกจากนี้เพียงแค่ต้องการเพิ่มที่นี่เพียงเพราะภาษา OO อื่น ๆ มีอินเทอร์เฟซและนามธรรมบางอย่างไม่ได้หมายความว่าพวกเขามีความหมายและวัตถุประสงค์เช่นเดียวกับใน PHP การใช้ abstraction / interfaces แตกต่างกันเล็กน้อยในขณะที่ส่วนติดต่อใน PHP ไม่มีฟังก์ชั่นจริง ใช้เพื่อเหตุผลเชิงความหมายและเกี่ยวข้องกับโครงการเท่านั้น ประเด็นคือต้องมีโครงการที่ยืดหยุ่นมากที่สุดขยายได้และปลอดภัยสำหรับส่วนขยายในอนาคตโดยไม่คำนึงว่าผู้พัฒนาจะมีแผนการใช้งานที่แตกต่างออกไปโดยสิ้นเชิงหรือไม่
หากภาษาอังกฤษของคุณไม่ใช่เจ้าของภาษาคุณอาจค้นหาว่า Abstraction and Interfaces คืออะไร และมองหาคำพ้องความหมายด้วย
และนี่อาจช่วยคุณในฐานะอุปมา:
อินเตอร์เฟซ
สมมติว่าคุณอบเค้กสตรอเบอร์รี่รูปแบบใหม่แล้วทำสูตรอธิบายส่วนผสมและขั้นตอน มีเพียงคุณเท่านั้นที่รู้ว่าทำไมรสชาติจึงอร่อยและแขกของคุณชอบ จากนั้นคุณตัดสินใจที่จะเผยแพร่สูตรของคุณเพื่อให้คนอื่นสามารถลองทำเค้กด้วยเช่นกัน
จุดนี่คือ
- เพื่อให้ถูกต้อง
- ระวัง
- เพื่อป้องกันสิ่งต่าง ๆ ที่อาจเลว (เช่นสตรอเบอร์รี่หรืออะไรบางอย่างมากเกินไป)
- เพื่อให้ง่ายสำหรับผู้ที่ลองใช้
- เพื่อบอกให้คุณรู้ว่าต้องทำนานแค่ไหน (เช่น stiring )
- เพื่อบอกสิ่งที่คุณสามารถทำได้ แต่ไม่ต้องทำ
ตรงนี้เป็นสิ่งที่อธิบายถึงอินเทอร์เฟซ มันเป็นคู่มือชุดของคำแนะนำที่สังเกตเนื้อหาของสูตร เหมือนกับว่าคุณจะสร้างโครงการใน PHP และคุณต้องการระบุรหัสใน GitHub หรือกับเพื่อนหรืออะไรก็ตาม อินเทอร์เฟซคือสิ่งที่ผู้คนสามารถทำได้และสิ่งที่คุณไม่ควรทำ กฎที่เก็บไว้ - หากคุณไม่เชื่อฟังสิ่งปลูกสร้างทั้งหมดจะถูกทำลาย
สิ่งที่เป็นนามธรรม
เมื่อต้องการเปรียบเทียบกับอุปมานี้ที่นี่ ... ลองนึกภาพคุณเป็นแขกรับเชิญในครั้งนี้ที่กินเค้กนั้น ถ้าอย่างนั้นคุณก็ลองเค้กที่ใช้สูตรตอนนี้ แต่คุณต้องการเพิ่มส่วนผสมใหม่หรือเปลี่ยน / ข้ามขั้นตอนที่อธิบายไว้ในสูตร แล้วจะเกิดอะไรขึ้นต่อไป วางแผนเค้กรุ่นอื่น เวลานี้มีแบล็กเบอร์รี่สีดำไม่ใช่สตรอเบอรี่และครีมวานิลลาอีกมาก ...
นี่คือสิ่งที่คุณสามารถพิจารณาส่วนขยายของเค้กดั้งเดิม คุณทำสิ่งที่เป็นนามธรรมโดยสร้างสูตรใหม่เพราะมันแตกต่างกันไป มีขั้นตอนใหม่ไม่กี่ขั้นตอนและส่วนผสมอื่น ๆ อย่างไรก็ตามแบล็กเบอร์รี่สีดำมีบางส่วนที่คุณรับช่วงต่อจากต้นฉบับ - นี่คือขั้นตอนพื้นฐานที่เค้กทุกชนิดต้องมี เช่นเดียวกับส่วนผสมเช่นเดียวกับนม - นั่นคือสิ่งที่ทุกชั้นได้รับ
ตอนนี้คุณต้องการแลกเปลี่ยนส่วนผสมและขั้นตอนต่าง ๆ และต้องกำหนดเหล่านี้ในเค้กรุ่นใหม่ เหล่านี้เป็นวิธีการเชิงนามธรรมที่จะต้องกำหนดสำหรับเค้กใหม่เพราะควรจะมีผลไม้ในเค้ก แต่ที่? คราวนี้คุณเอาผลเบอร์รี่สีดำ เสร็จสิ้น
คุณไปแล้วคุณได้ขยายเค้กทำตามอินเทอร์เฟซและขั้นตอนที่เป็นนามธรรมและส่วนผสมจากมัน
หากต้องการเพิ่มคำตอบที่ยอดเยี่ยมบางส่วน:
คลาสที่เป็นนามธรรมให้คุณจัดเตรียมการใช้งานบางส่วนอินเทอร์เฟซเป็นเทมเพลตแท้ อินเทอร์เฟซสามารถกำหนดฟังก์ชันการทำงานเท่านั้นมันไม่สามารถใช้งานได้
คลาสใด ๆ ที่ใช้อินเทอร์เฟซมุ่งมั่นที่จะใช้วิธีการทั้งหมดที่กำหนดหรือจะต้องประกาศนามธรรม
อินเทอร์เฟซสามารถช่วยในการจัดการความจริงที่ว่าเช่น Java, PHP ไม่สนับสนุนการสืบทอดหลายอย่าง คลาส PHP สามารถขยายพาเรนต์เดียวเท่านั้น อย่างไรก็ตามคุณสามารถสร้างคลาสสัญญาเพื่อใช้อินเทอร์เฟซได้มากเท่าที่คุณต้องการ
type: สำหรับแต่ละอินเตอร์เฟสที่ใช้คลาสจะใช้ชนิดที่สอดคล้องกัน เนื่องจากคลาสใด ๆ สามารถใช้อินเทอร์เฟซ (หรืออินเทอร์เฟซเพิ่มเติม), อินเทอร์เฟซการรวมชนิดที่ไม่เกี่ยวข้องได้อย่างมีประสิทธิภาพ
คลาสสามารถขยายซูเปอร์คลาสและใช้อินเตอร์เฟสจำนวนเท่าใดก็ได้:
class SubClass extends ParentClass implements Interface1, Interface2 {
// ...
}
โปรดอธิบายเมื่อฉันควรใช้อินเทอร์เฟซและเมื่อใดที่ฉันควรใช้คลาสนามธรรม?
ใช้อินเทอร์เฟซเมื่อคุณต้องการให้เฉพาะเทมเพลตที่ไม่มีการใช้งานและคุณต้องการตรวจสอบให้แน่ใจว่าคลาสใดที่ใช้อินเทอร์เฟซนั้นจะมีวิธีการเดียวกันกับคลาสอื่น ๆ ที่ใช้งาน (อย่างน้อย)
ใช้คลาสนามธรรมเมื่อคุณต้องการสร้างรากฐานสำหรับวัตถุอื่น (คลาสที่สร้างขึ้นบางส่วน) คลาสที่ขยายคลาสนามธรรมของคุณจะใช้คุณสมบัติหรือวิธีการบางอย่างที่กำหนด / นำไปใช้:
<?php
// interface
class X implements Y { } // this is saying that "X" agrees to speak language "Y" with your code.
// abstract class
class X extends Y { } // this is saying that "X" is going to complete the partial class "Y".
?>
ฉันจะเปลี่ยนคลาสนามธรรมของฉันเป็นอินเทอร์เฟซได้อย่างไร
นี่คือกรณี / ตัวอย่างที่ง่ายขึ้น นำรายละเอียดการใช้งานออกมา ตัวอย่างเช่นเปลี่ยนคลาสนามธรรมของคุณจาก:
abstract class ClassToBuildUpon {
public function doSomething() {
echo 'Did something.';
}
}
ถึง:
interface ClassToBuildUpon {
public function doSomething();
}
จากมุมมองของ phylosophic:
คลาสนามธรรมหมายถึงความสัมพันธ์ "คือ" ให้บอกว่าฉันมีผลไม้เอาล่ะฉันจะมีคลาสนามธรรมที่มีความรับผิดชอบร่วมกันและพฤติกรรมทั่วไป
อินเทอร์เฟซแสดงถึงความสัมพันธ์ "ควรทำ" อินเทอร์เฟซในความคิดของฉัน (ซึ่งเป็นความคิดเห็นของนักพัฒนาซอฟต์แวร์ระดับต้น) ควรได้รับการตั้งชื่อจากการกระทำหรือสิ่งที่ใกล้เคียงกับการกระทำ (ขออภัยไม่สามารถหาคำได้ฉันไม่ใช่เจ้าของภาษาอังกฤษ) สมมติว่า IEatable คุณรู้ว่ามันกินได้ แต่คุณไม่รู้ว่าคุณกินอะไร
จากมุมมองการเข้ารหัส:
หากวัตถุของคุณมีรหัสที่ซ้ำกันมันเป็นการบ่งชี้ว่าพวกเขามีพฤติกรรมที่เหมือนกันซึ่งหมายความว่าคุณอาจต้องการคลาสนามธรรมเพื่อนำรหัสมาใช้ซ้ำซึ่งคุณไม่สามารถทำได้ด้วยอินเทอร์เฟซ
ความแตกต่างอีกอย่างคือวัตถุสามารถใช้อินเทอร์เฟซได้มากเท่าที่คุณต้องการ แต่คุณสามารถมีคลาสนามธรรมเพียงอันเดียวเนื่องจาก "ปัญหาเพชร" (ลองดูที่นี่เพื่อทราบว่าทำไม! http://en.wikipedia.org/wiki/ Multiple_inheritance # The_diamond_problem )
ฉันอาจลืมบางจุด แต่ฉันหวังว่ามันจะสามารถชี้แจงสิ่งต่าง ๆ ได้
PS: "เป็น" / "ควรทำ" ถูกนำโดยคำตอบของ Vivek Vermani ฉันไม่ได้ตั้งใจจะขโมยคำตอบของเขาเพียงเพื่อนำคำศัพท์มาใช้ใหม่เพราะฉันชอบพวกเขา!
ความแตกต่างทางเทคนิคระหว่างคลาสนามธรรมและอินเทอร์เฟซถูกแสดงรายการไว้แล้วในคำตอบอื่น ๆ อย่างแม่นยำ ฉันต้องการเพิ่มคำอธิบายเพื่อเลือกระหว่างคลาสและอินเทอร์เฟซในขณะที่เขียนโค้ดเพื่อประโยชน์ของการเขียนโปรแกรมเชิงวัตถุ
คลาสควรแสดงเอนทิตีในขณะที่อินเทอร์เฟซควรแสดงพฤติกรรม
ลองยกตัวอย่าง จอภาพคอมพิวเตอร์เป็นเอนทิตีและควรแสดงเป็นคลาส
class Monitor{
private int monitorNo;
}
มันถูกออกแบบมาเพื่อให้อินเทอร์เฟซการแสดงผลให้กับคุณดังนั้นควรกำหนดฟังก์ชันการทำงานโดยอินเทอร์เฟซ
interface Display{
void display();
}
ยังมีอีกหลายสิ่งที่ต้องพิจารณาตามที่อธิบายไว้ในคำตอบอื่น ๆ แต่นี่เป็นสิ่งพื้นฐานที่สุดที่คนส่วนใหญ่ไม่สนใจขณะที่เขียนโค้ด
PHP
แค่ต้องการเพิ่มตัวอย่างเมื่อคุณอาจต้องใช้ทั้งสองอย่าง ฉันกำลังเขียนตัวจัดการไฟล์ที่ถูกผูกไว้กับโมเดลฐานข้อมูลในโซลูชัน ERP สำหรับวัตถุประสงค์ทั่วไป
ด้วยวิธีนี้ฉันจะมีเทมเพลตจำนวนมากสำหรับไฟล์ที่แตกต่างกันและชุดวิธีอินเทอร์เฟซทั่วไปที่มีความแตกต่างชัดเจน อินเตอร์เฟสให้การเปรียบเทียบที่ถูกต้องกับวิธีการเข้าถึงมากกว่าสิ่งที่จะเกิดขึ้นกับคลาสนามธรรมพื้นฐาน
ยิ่งไปกว่านั้นเมื่อฉันจะทำให้อะแดปเตอร์สำหรับบริการจัดเก็บไฟล์ที่แตกต่างกันการใช้งานนี้จะช่วยให้อินเตอร์เฟซที่จะใช้ที่อื่นในบริบทที่แตกต่างกันโดยสิ้นเชิง
abstract
และinterface
ชั้นเรียนโพสต์ของคุณทำให้ชัดเจน ขอบคุณมาก Alan