โปรดอธิบายเมื่อฉันควรใช้ 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