ตกลงเพื่อนของฉันกลับไปกลับมาว่า "อินเทอร์เฟซ" หมายถึงอะไรในการเขียนโปรแกรม
คำอธิบายที่ดีที่สุดของ "อินเทอร์เฟซ" คืออะไร
สำหรับฉันแล้วอินเทอร์เฟซเป็นพิมพ์เขียวของชั้นเรียนนี่เป็นคำจำกัดความที่ดีที่สุดหรือไม่?
ตกลงเพื่อนของฉันกลับไปกลับมาว่า "อินเทอร์เฟซ" หมายถึงอะไรในการเขียนโปรแกรม
คำอธิบายที่ดีที่สุดของ "อินเทอร์เฟซ" คืออะไร
สำหรับฉันแล้วอินเทอร์เฟซเป็นพิมพ์เขียวของชั้นเรียนนี่เป็นคำจำกัดความที่ดีที่สุดหรือไม่?
คำตอบ:
อินเทอร์เฟซเป็นหนึ่งในคำศัพท์ที่มากเกินไปและสับสนในการพัฒนา
เป็นแนวคิดของนามธรรมและการห่อหุ้ม สำหรับ "กล่อง" ที่กำหนดจะประกาศ "อินพุต" และ "เอาต์พุต" ของกล่องนั้น ในโลกของซอฟต์แวร์นั้นมักหมายถึงการดำเนินการที่สามารถเรียกใช้บนกล่อง (พร้อมกับอาร์กิวเมนต์) และในบางกรณีประเภทการส่งคืนของการดำเนินการเหล่านี้
สิ่งที่ไม่ทำคือกำหนดว่าความหมายของการดำเนินการเหล่านี้คืออะไรแม้ว่าจะเป็นเรื่องธรรมดา (และเป็นแนวปฏิบัติที่ดีมาก) ในการจัดทำเอกสารใกล้เคียงกับการประกาศ (เช่นผ่านความคิดเห็น) หรือเพื่อเลือกรูปแบบการตั้งชื่อที่ดี อย่างไรก็ตามไม่มีการรับประกันว่าความตั้งใจเหล่านี้จะเป็นไปตามนั้น
นี่คือการเปรียบเทียบ: ลองดูที่โทรทัศน์ของคุณเมื่อปิดอยู่ อินเทอร์เฟซของมันคือปุ่มที่มีปลั๊กต่างๆและหน้าจอ ความหมายและพฤติกรรมของมันคือการรับอินพุต (เช่นการเขียนโปรแกรมเคเบิล) และมีเอาท์พุต (แสดงบนหน้าจอเสียง ฯลฯ ) อย่างไรก็ตามเมื่อคุณดูทีวีที่ไม่ได้เสียบปลั๊กคุณกำลังฉายความหมายที่คาดหวังไว้ในอินเทอร์เฟซ สำหรับทุกสิ่งที่คุณทราบทีวีอาจระเบิดได้เมื่อคุณเสียบปลั๊กอย่างไรก็ตามจาก "อินเทอร์เฟซ" คุณสามารถสันนิษฐานได้ว่าจะไม่ชงกาแฟใด ๆ เนื่องจากไม่มีการดื่มน้ำ
ในการเขียนโปรแกรมเชิงวัตถุโดยทั่วไปอินเทอร์เฟซจะกำหนดชุดวิธีการ (หรือข้อความ) ที่อินสแตนซ์ของคลาสที่มีอินเตอร์เฟสนั้นสามารถตอบสนองได้
สิ่งที่เพิ่มความสับสนคือในบางภาษาเช่น Java มีอินเทอร์เฟซจริงที่มีความหมายเฉพาะของภาษา ตัวอย่างเช่นใน Java เป็นชุดของการประกาศเมธอดโดยไม่มีการนำไปใช้ แต่อินเทอร์เฟซยังสอดคล้องกับประเภทและปฏิบัติตามกฎการพิมพ์ต่างๆ
ในภาษาอื่น ๆ เช่น C ++ คุณไม่มีอินเทอร์เฟซ คลาสนั้นกำหนดวิธีการเอง แต่คุณอาจคิดว่าอินเทอร์เฟซของคลาสเป็นการประกาศของเมธอดที่ไม่ใช่ไพรเวต เนื่องจากวิธีการรวบรวม C ++ คุณจะได้รับไฟล์ส่วนหัวซึ่งคุณสามารถมี "อินเทอร์เฟซ" ของคลาสได้โดยไม่ต้องใช้งานจริง คุณยังสามารถเลียนแบบอินเตอร์เฟส Java กับคลาสนามธรรมที่มีฟังก์ชันเสมือนจริงเป็นต้น
อินเทอร์เฟซไม่ใช่พิมพ์เขียวสำหรับคลาส พิมพ์เขียวหนึ่งคำจำกัดความคือ "แผนปฏิบัติการโดยละเอียด" อินเทอร์เฟซไม่มีอะไรเกี่ยวกับการกระทำ! แหล่งที่มาของความสับสนคือในภาษาส่วนใหญ่หากคุณมีประเภทอินเทอร์เฟซที่กำหนดชุดของวิธีการคลาสที่ใช้มันจะ "ทำซ้ำ" ด้วยวิธีการเดียวกัน (แต่ให้คำจำกัดความ) อินเทอร์เฟซจึงดูเหมือนโครงกระดูกหรือ โครงร่างของชั้นเรียน
พิจารณาสถานการณ์ต่อไปนี้:
คุณอยู่กลางห้องว่างเปล่าขนาดใหญ่เมื่อจู่ๆซอมบี้ก็โจมตีคุณ
คุณไม่มีอาวุธ
โชคดีที่เพื่อนมนุษย์ที่ยังมีชีวิตยืนอยู่ตรงประตูห้อง
"ด่วน!" คุณตะโกนใส่เขา "โยนของที่ฉันสามารถตีซอมบี้ให้ฉันได้!"
ตอนนี้พิจารณา:
คุณไม่ได้ระบุ (หรือทำคุณดูแล) ว่าสิ่งที่เพื่อนของคุณจะเลือกที่จะโยน;
... แต่ไม่เป็นไรตราบใดที่:
มันเป็นสิ่งที่สามารถจะโยน (เขาไม่สามารถโยนคุณโซฟา)
เป็นสิ่งที่คุณสามารถคว้าได้ (หวังว่าเขาจะไม่โยนชูริเคน)
มันเป็นสิ่งที่คุณสามารถใช้เพื่อทุบสมองของซอมบี้ออก (นั่นคือกฎของหมอนและอื่น ๆ )
ไม่สำคัญว่าคุณจะได้ไม้เบสบอลหรือค้อน -
ตราบใดที่มันเป็นไปตามเงื่อนไขสามประการคุณก็ทำได้ดี
สรุปได้:
เมื่อคุณเขียนอินเทอร์เฟซโดยพื้นฐานแล้วคุณจะพูดว่า: "ฉันต้องการบางสิ่งที่ ... "
อินเทอร์เฟซคือสัญญาที่คุณควรปฏิบัติตามหรือมอบให้ขึ้นอยู่กับว่าคุณเป็นผู้ใช้หรือผู้ใช้
ฉันไม่คิดว่า "พิมพ์เขียว" เป็นคำที่ดีที่จะใช้ พิมพ์เขียวบอกวิธีสร้างบางสิ่ง อินเทอร์เฟซหลีกเลี่ยงการบอกวิธีสร้างบางสิ่งโดยเฉพาะ
อินเทอร์เฟซกำหนดวิธีที่คุณสามารถโต้ตอบกับคลาสกล่าวคือรองรับวิธีการใด
สำหรับฉันแล้วอินเทอร์เฟซเป็นพิมพ์เขียวของชั้นเรียนนี่เป็นคำจำกัดความที่ดีที่สุดหรือไม่?
ไม่โดยทั่วไปพิมพ์เขียวจะรวมถึงภายใน แต่อินเทอร์เฟซนั้นเกี่ยวกับสิ่งที่มองเห็นได้จากภายนอกคลาสเท่านั้น ... หรือที่ถูกต้องกว่านั้นคือกลุ่มคลาสที่ใช้อินเทอร์เฟซ
อินเทอร์เฟซประกอบด้วยลายเซ็นของวิธีการและค่าของค่าคงที่และยังมี "สัญญาพฤติกรรม" (โดยทั่วไปไม่เป็นทางการ) ระหว่างคลาสที่ใช้อินเทอร์เฟซและอื่น ๆ ที่ใช้
ในการเขียนโปรแกรมอินเทอร์เฟซจะกำหนดลักษณะการทำงานของอ็อบเจ็กต์ แต่จะไม่ระบุลักษณะการทำงานจริง เป็นสัญญาที่จะรับประกันว่าชนชั้นหนึ่งสามารถทำบางสิ่งได้
พิจารณารหัส C # ชิ้นนี้ที่นี่:
using System;
public interface IGenerate
{
int Generate();
}
// Dependencies
public class KnownNumber : IGenerate
{
public int Generate()
{
return 5;
}
}
public class SecretNumber : IGenerate
{
public int Generate()
{
return new Random().Next(0, 10);
}
}
// What you care about
class Game
{
public Game(IGenerate generator)
{
Console.WriteLine(generator.Generate())
}
}
new Game(new SecretNumber());
new Game(new KnownNumber());
คลาสเกมต้องใช้หมายเลขลับ เพื่อประโยชน์ในการทดสอบคุณต้องการฉีดสิ่งที่จะใช้เป็นหมายเลขลับ (หลักการนี้เรียกว่า Inversion of Control)
คลาสเกมต้องการที่จะ "เปิดใจ" เกี่ยวกับสิ่งที่จะสร้างตัวเลขสุ่มจริงๆดังนั้นมันจะถามในตัวสร้างสำหรับ "อะไรก็ได้ที่มีเมธอดสร้าง"
ขั้นแรกอินเทอร์เฟซระบุว่าการดำเนินการใดที่วัตถุจะให้ มันมีเพียงสิ่งที่ดูเหมือน แต่ไม่มีการนำไปใช้จริง นี่เป็นเพียงลายเซ็นของวิธีการ ตามปกติแล้วในอินเทอร์เฟซ C # จะขึ้นต้นด้วย I ขณะนี้คลาสใช้อินเทอร์เฟซ IGenerate ซึ่งหมายความว่าคอมไพลเลอร์จะตรวจสอบให้แน่ใจว่าทั้งคู่มีเมธอดที่ส่งคืน int และถูกเรียกใช้Generate
ใช้ ตอนนี้เกมนี้ถูกเรียกว่าออบเจ็กต์สองชิ้นที่แตกต่างกันซึ่งแต่ละตัวใช้อินเทอร์เฟซที่ถูกต้อง คลาสอื่น ๆ จะทำให้เกิดข้อผิดพลาดในการสร้างโค้ด
ที่นี่ฉันสังเกตเห็นการเปรียบเทียบแบบพิมพ์เขียวที่คุณใช้:
คลาสมักถูกมองว่าเป็นพิมพ์เขียวสำหรับวัตถุ อินเทอร์เฟซระบุบางสิ่งบางอย่างที่คลาสจะต้องทำดังนั้นใคร ๆ ก็สามารถโต้แย้งได้ว่ามันเป็นแค่พิมพ์เขียวของคลาส แต่เนื่องจากคลาสไม่จำเป็นต้องมีอินเทอร์เฟซฉันจึงขอยืนยันว่าอุปมานี้กำลังทำลาย คิดว่าอินเทอร์เฟซเป็นสัญญา ชั้นเรียนที่ "ลงนาม" จะต้องถูกต้องตามกฎหมาย (บังคับโดยตำรวจคอมไพเลอร์) เพื่อปฏิบัติตามข้อกำหนดและเงื่อนไขในสัญญา ซึ่งหมายความว่าจะต้องทำสิ่งที่ระบุไว้ในอินเทอร์เฟซ
ทั้งหมดนี้เกิดจากลักษณะการพิมพ์แบบคงที่ของภาษา OO บางภาษาเนื่องจากเป็นกรณีของ Java หรือ C # ในทางกลับกันใน Python จะใช้กลไกอื่น:
import random
# Dependencies
class KnownNumber(object):
def generate(self):
return 5
class SecretNumber(object):
def generate(self):
return random.randint(0,10)
# What you care about
class SecretGame(object):
def __init__(self, number_generator):
number = number_generator.generate()
print number
ที่นี่ไม่มีคลาสใดที่ใช้อินเทอร์เฟซ Python ไม่สนใจเรื่องนั้นเพราะSecretGame
คลาสจะพยายามเรียกสิ่งที่ส่งผ่านเข้ามาถ้าอ็อบเจกต์มีวิธีการสร้าง () ทุกอย่างก็เรียบร้อยดี ถ้าไม่มี: KAPUTT! ข้อผิดพลาดนี้จะไม่ปรากฏให้เห็นในเวลาคอมไพล์ แต่ในขณะรันไทม์อาจเป็นไปได้ว่าเมื่อโปรแกรมของคุณถูกปรับใช้และรันอยู่แล้ว C # จะแจ้งให้คุณทราบก่อนที่คุณจะเข้าใกล้สิ่งนั้น
เหตุผลที่ใช้กลไกนี้ระบุอย่างไร้เดียงสาเพราะในภาษา OO โดยธรรมชาติแล้วฟังก์ชันไม่ใช่พลเมืองชั้นหนึ่ง อย่างที่คุณเห็นKnownNumber
และSecretNumber
มีเพียงฟังก์ชั่นในการสร้างตัวเลข หนึ่งไม่จำเป็นต้องเรียนเลย ดังนั้นใน Python เราสามารถทิ้งมันไปและเลือกฟังก์ชั่นได้ด้วยตัวเอง:
# OO Approach
SecretGame(SecretNumber())
SecretGame(KnownNumber())
# Functional Approach
# Dependencies
class SecretGame(object):
def __init__(self, generate):
number = generate()
print number
SecretGame(lambda: random.randint(0,10))
SecretGame(lambda: 5)
แลมบ์ดาเป็นเพียงฟังก์ชันซึ่งถูกประกาศว่า "ตามลำดับขณะที่คุณไป" ผู้รับมอบสิทธิ์เหมือนกันใน C #:
class Game
{
public Game(Func<int> generate)
{
Console.WriteLine(generate())
}
}
new Game(() => 5);
new Game(() => new Random().Next(0, 10));
หมายเหตุด้านข้าง: ตัวอย่างหลังไม่สามารถทำได้เช่นนี้จนถึง Java 7 ที่นั่นอินเทอร์เฟซเป็นวิธีเดียวของคุณในการระบุพฤติกรรมนี้ อย่างไรก็ตาม Java 8 แนะนำนิพจน์แลมบ์ดาเพื่อให้ตัวอย่าง C # สามารถแปลงเป็น Java ได้ง่ายมาก ( Func<int>
กลายเป็นjava.util.function.IntSupplier
และ=>
กลายเป็น->
)
ในทางเทคนิคฉันจะอธิบายอินเทอร์เฟซเป็นชุดของวิธีการ (วิธีการคุณสมบัติตัวเข้าถึง ... คำศัพท์ขึ้นอยู่กับภาษาที่คุณใช้) เพื่อโต้ตอบกับวัตถุ หากออบเจ็กต์รองรับ / ใช้งานอินเทอร์เฟซคุณสามารถใช้ทุกวิธีที่ระบุในอินเทอร์เฟซเพื่อโต้ตอบกับออบเจ็กต์นี้
ในทางความหมายอินเทอร์เฟซอาจมีข้อตกลงเกี่ยวกับสิ่งที่คุณอาจจะทำหรือไม่ทำก็ได้ (เช่นลำดับที่คุณอาจเรียกว่าเมธอด) และในทางกลับกันคุณอาจคิดเกี่ยวกับสถานะของอ็อบเจ็กต์ตามวิธีที่คุณโต้ตอบ ไกล.
โดยส่วนตัวแล้วฉันเห็นอินเทอร์เฟซเหมือนเทมเพลต หากอินเทอร์เฟซมีนิยามสำหรับเมธอด foo () และ bar () แสดงว่าทุกคลาสที่ใช้อินเทอร์เฟซนี้มีเมธอด foo () และ bar ()
ให้เราพิจารณาผู้ชาย (ผู้ใช้หรือวัตถุ) ต้องการให้งานบางอย่างเสร็จสิ้น เขาจะติดต่อกับชายกลางคน (ส่วนต่อประสาน) ซึ่งจะทำสัญญากับ บริษัท ต่างๆ (วัตถุในโลกแห่งความจริงที่สร้างขึ้นโดยใช้คลาสที่ใช้งาน) เขาจะกำหนดงานไม่กี่ประเภทว่า บริษัท ใดจะนำไปปฏิบัติและให้ผลลัพธ์แก่เขา แต่ละ บริษัท จะนำผลงานไปใช้ในแบบของตัวเอง แต่ผลลัพธ์จะเหมือนกัน เช่นเดียวกับผู้ใช้รายนี้จะทำงานให้เสร็จโดยใช้อินเทอร์เฟซเดียว ฉันคิดว่าอินเทอร์เฟซจะทำหน้าที่เป็นส่วนที่มองเห็นได้ของระบบที่มีคำสั่งไม่กี่คำสั่งซึ่งจะถูกกำหนดภายในโดยการนำระบบย่อยภายในไปใช้
อินเทอร์เฟซแยกการดำเนินการในคลาสออกจากการใช้งานภายใน ดังนั้นการใช้งานบางอย่างอาจจัดเตรียมไว้สำหรับอินเทอร์เฟซจำนวนมาก
ผู้คนมักจะอธิบายว่ามันเป็น "สัญญา" สำหรับสิ่งที่ต้องมีในวิธีการของคลาส
ไม่ใช่พิมพ์เขียวอย่างแน่นอนเนื่องจากจะกำหนดการใช้งานด้วย นิยามคลาสเต็มอาจกล่าวได้ว่าเป็นพิมพ์เขียว
อินเทอร์เฟซกำหนดสิ่งที่คลาสที่สืบทอดมาจากมันต้องนำไปใช้ ด้วยวิธีนี้หลายคลาสสามารถสืบทอดจากอินเทอร์เฟซและเนื่องจากการสืบทอดนั้นคุณสามารถทำได้
สำหรับข้อมูลเพิ่มเติมโปรดดูที่http://msdn.microsoft.com/en-us/library/ms173156.aspx
ในความคิดของฉันอินเทอร์เฟซมีความหมายกว้างกว่าอินเทอร์เฟซที่เกี่ยวข้องโดยทั่วไปใน Java ฉันจะกำหนด "อินเทอร์เฟซ" เป็นชุดของการดำเนินการที่พร้อมใช้งานพร้อมฟังก์ชันการทำงานทั่วไปบางอย่างที่อนุญาตให้ควบคุม / ตรวจสอบโมดูล
ในคำจำกัดความนี้ฉันพยายามที่จะครอบคลุมทั้งอินเทอร์เฟซแบบเป็นโปรแกรมโดยที่ไคลเอนต์เป็นโมดูลบางตัวและอินเทอร์เฟซสำหรับมนุษย์ (เช่น GUI)
อย่างที่คนอื่น ๆ พูดไปแล้วอินเทอร์เฟซมักจะมีสัญญาบางอย่างอยู่ข้างหลังในแง่ของอินพุตและเอาต์พุต อินเทอร์เฟซไม่ได้สัญญาอะไรเกี่ยวกับ "วิธีการ" ของการดำเนินการ มันรับประกันคุณสมบัติบางอย่างของผลลัพธ์เท่านั้นโดยพิจารณาจากสถานะปัจจุบันการดำเนินการที่เลือกและพารามิเตอร์
ข้างต้นคำพ้องความหมายของ "สัญญา" และ "โปรโตคอล" มีความเหมาะสม
อินเทอร์เฟซประกอบด้วยวิธีการและคุณสมบัติที่คุณคาดว่าจะได้รับจากคลาส
ดังนั้นถ้าชั้นเรียนCheetos Bag
ดำเนินการChip Bag
อินเตอร์เฟซที่คุณควรคาดหวังว่าจะทำตัวเหมือนคนอื่นCheetos Bag
ๆ Chip Bag
(นั่นคือเปิดเผย.attemptToOpenWithoutSpillingEverywhere()
วิธีการ ฯลฯ )
นิยามทั่วไป - อินเทอร์เฟซคือสัญญาที่ระบุวิธีการที่จำเป็นต้องดำเนินการโดยคลาสที่นำไปใช้
ความหมายของอินเทอร์เฟซมีการเปลี่ยนแปลงอยู่ตลอดเวลา คุณคิดว่าอินเทอร์เฟซมีเพียงการประกาศวิธีการเท่านั้นหรือไม่? สิ่งที่เกี่ยวกับตัวแปรสุดท้ายแบบคงที่และสิ่งที่เกี่ยวกับนิยามดีฟอลต์หลังจาก Java 5
อินเทอร์เฟซถูกนำมาใช้กับ Java เนื่องจากปัญหา Diamond ที่มีการสืบทอดหลายรายการและนั่นคือสิ่งที่พวกเขาตั้งใจจะทำจริงๆ
อินเทอร์เฟซเป็นโครงสร้างที่สร้างขึ้นเพื่อหลีกเลี่ยงปัญหาการสืบทอดหลาย ๆ แบบและอาจมีวิธีการนามธรรมนิยามเริ่มต้นและตัวแปรสุดท้ายแบบคงที่
อินเตอร์เฟซที่มีวิธีการบางภาษา OO บรรลุเฉพาะกิจ polymorphism Ad hoc polymorphism เป็นเพียงฟังก์ชันที่มีชื่อเดียวกันซึ่งทำงานในประเภทต่างๆ