เพิ่งเริ่มหัดเขียนโปรแกรม OOP อ่านหนังสือแล้วเจอตอนใช้ Dictionary ตอนประกาศตัวแปรกลับใช้ IDictionary แทน

IDictionary<string, MyClass> dictionary = new Dictionary<string, MyClass>();

ทำไมถึงไม่ใช้

Dictionary<string, MyClass> dictionary = new Dictionary<string, MyClass>();

ทั้งที่การประกาศทั้งสองแบบก็สามารถใช้งาน Dictionary Class ได้เหมือนกัน พยายามลองหาเหตุผลจาก google แล้ว คำตอบที่ได้ไม่ค่อยชัดเจนเท่าไหร่

คำตอบที่พบเช่น

  • หากมีการแก้ไข code ในอนาคต ในกรณีที่ต้องการใช้ Class ในกลุ่มเดียวกัน สามารถทำได้ง่ายกว่า
  • บางคนบอกให้เลือกตามความเป็น generic มากกว่ากัน
  • สามารถ casting ไป Interface หรือ Class ในกลุ่มเดียวกันได้ง่ายกว่า

สรุปว่ามันจำเป็นไหมครับ? ถ้ามันจำเป็นหรือมีข้อดีอื่น ๆ รบกวนช่วยอธิบายหรือตัวอย่าง code ที่จำเป็นต่อการใช้งานแบบนี้ ถ้ามันดีกว่าจริง แล้วเราจะรู้ได้อย่างไรว่า Class ไหนควรประกาศตัวแปรด้วย Interface แทนการใช้ Class ประกาศตรง ๆ ครับ

ผมลองเขียนโปรแกรม casting ดูมันก็สามารถทำได้อยู่แล้วเลยยิ่งสงสัยว่าจะทำไปทำไม

class Program
{
    static void Main(string[] args)
    {
        Dictionary<string, int> myVar = new Dictionary();

        myVar.Add("a", 1000);
        myVar.Add("b", 2000);

        foreach(KeyValuePair<string, int> x in myVar)
        {
            Console.WriteLine("\"{0}\" => {1}", x.Key, x.Value);
        }

        Console.WriteLine("Casting to IDictionary.");

        IDictionary<string, int> testVar = (IDictionary<string, int>)myVar;

        foreach (KeyValuePair<string, int> x in testVar)
        {
            Console.WriteLine("\"{0}\" => {1}", x.Key, x.Value);
        }
    }
}

output:

"a" => 1000
"b" => 2000
Casting to IDictionary.
"a" => 1000
"b" => 2000

Hiring! บริษัทที่น่าสนใจ

Carmen Software company cover
Carmen Software
Hotel Financial Solutions
Next Innovation (Thailand) Co., Ltd. company cover
Next Innovation (Thailand) Co., Ltd.
We are web design with consulting & engineering services driven the future stronger and flexibility.
KKP Dime company cover
KKP Dime
KKP Dime บริษัทในเครือเกียรตินาคินภัทร
Kiatnakin Phatra Financial Group company cover
Kiatnakin Phatra Financial Group
Financial Service
Fastwork Technologies company cover
Fastwork Technologies
Fastwork.co เว็บไซต์ที่รวบรวม ฟรีแลนซ์ มืออาชีพจากหลากหลายสายงานไว้ในที่เดียวกัน
Thoughtworks Thailand company cover
Thoughtworks Thailand
Thoughtworks เป็นบริษัทที่ปรึกษาด้านเทคโนโยลีระดับโลกที่คว้า Great Place to Work 3 ปีซ้อน
Iron Software company cover
Iron Software
Iron Software is an American company providing a suite of .NET libraries by engineer for engineers.
CLEVERSE company cover
CLEVERSE
Cleverse is a Venture Builder. Our team builds several tech companies.
Nipa Cloud company cover
Nipa Cloud
#1 OpenStack cloud provider in Thailand with our own data center and software platform.
Bangmod Enterprise company cover
Bangmod Enterprise
The leader in Cloud Server and Hosting in Thailand.
CIMB THAI Bank company cover
CIMB THAI Bank
MOVING FORWARD WITH YOU - CIMB is the leading ASEAN Bank
Bangkok Bank company cover
Bangkok Bank
Bangkok Bank is one of Southeast Asia's largest regional banks, a market leader in business banking
MuvMi (Urban Mobility Tech Co.,Ltd.) company cover
MuvMi (Urban Mobility Tech Co.,Ltd.)
Shape the future of urban mobility towards affordable, clean, and safe solutions
T.N. Digital Solution Co., Ltd. company cover
T.N. Digital Solution Co., Ltd.
TNDS has been involving in every first move of banking’s major digital transformation.
KBTG - KASIKORN Business-Technology Group company cover
KBTG - KASIKORN Business-Technology Group
KBTG - "The Technology Company for Digital Business Innovation"
Siam Commercial Bank Public Company Limited company cover
Siam Commercial Bank Public Company Limited
"Let's start a brighter career future together"
Icon Framework co.,Ltd. company cover
Icon Framework co.,Ltd.
Global Standard Platform for Real Estate แพลตฟอร์มสำหรับธุรกิจอสังหาริมทรัพย์ครบวงจร มาตรฐานระดับโลก
REFINITIV company cover
REFINITIV
The Financial and Risk business of Thomson Reuters is now Refinitiv
H LAB company cover
H LAB
Re-engineering healthcare systems through intelligent platforms and system design.
The Gang Technology Co., Ltd. company cover
The Gang Technology Co., Ltd.
We're a Digital Agency that helps our customers transform their business into digital with ease.
LTMH company cover
LTMH
LTMH มุ่งเน้นการพัฒนาผลิตภัณฑ์ที่สามารถช่วยพันธมิตรของเราให้บรรลุเป้าหมาย
Seven Peaks company cover
Seven Peaks
We Drive Digital Transformation
Wisesight (Thailand) Co., Ltd. company cover
Wisesight (Thailand) Co., Ltd.
The Best Choice For Handling Social Media · High Expertise in Social Data · Most Advanced and Secure
MOLOG Tech company cover
MOLOG Tech
We are Modern Logistic Platform, Specialize in WMS, OMS and TMS.
Data Wow Co.,Ltd company cover
Data Wow Co.,Ltd
We enable our clients to realize increased productivity by solving their most complex issues by Data
LINE Company Thailand company cover
LINE Company Thailand
LINE, the world's hottest mobile messaging platform, offers free text and voice messaging + Call
LINE MAN Wongnai company cover
LINE MAN Wongnai
Join our journey to becoming No.1 food platform in Thailand

ผมจะอธิบายความหมายของ interface แล้วกันครับ

  • ใน interface จะมีแค่ method และ properties จะไม่สามารถเขียน code ไว้ใน Method ได้ครับ(ถ้าเขียน c# ตอนนี้ใน c# 7.0 จะทำได้มากกว่านี้ครับ)

ในกรณีของ IDictionary<string, MyClass> dictionary = new Dictionary<string, MyClass>();
ถ้าไปดูใน Class Dictionary จะมีการ inherited IDictionary ซึ่ง IDictionary เป็น interface ที่มีแต่ method กับ properites เท่านั้นครับ(จะตรงกับสิ่งที่ผมบอกอยู่ด้านบนครับ) และใน IDictionary เองนั้นยังมีการ
inherited ICollection, IEnumerable อีกด้วยครับ

ผมจะยกตัวอย่างให้เป็นภาพชัดครับ
interface IGetable
{
string Get();
}

interface IAll
{
string All();
}

class Example1 : IGetable, IAll
{
public string Get() { return "Get"; }
public string All() { return "All"; }
}

class Exp1
{
IGetable get1 = new Example1(); //Method ที่สามารถเรียกใช้ได้จะมีแค่ Get()
IAll get1 = new Example1(); //Method ที่สามารถเรียกใช้ได้จะมีแค่ All()
Example1 exp1 = new Example1(); //Method ที่สามารถเรียกใช้ได้จะมีแค่ Get() และ All
}

จากตัวอย่าง Exp1 จะเห็นว่า Example1 จะเป็น class ลูกและมี class แม่เป็น IGetable, IAll ครับ ถ้ามีการ new object จาก class ลูกใส่ใน class แม่ก็จะมีแค่ความสามารถของแม่ครับ

ส่วนถามว่าจำเป็นไม ตอบเลยครับว่าจำเป็นครับ สำหรับ OOP และการเขียนโปรแกรมที่ถูกตามมาตรฐานสากลครับ
ข้อดี OOP มีเยอะมากๆ ครับ

ส่วนที่ถามว่า จะรู้ได้ยังไงว่า Class ไหนจะต้องใช้ Interface หรือใช้ Class แทนได้
ตอบ ถ้าโปรแกรมของคุณมีการเรียกใช้งานจากโปรแกรมอื่นๆ ตรงนี้แนะนำให้ใช้ Interface แทน base class ครับ
ตัวอย่างคือ ถ้าโปรแกรมของคุณต้องการจะทำการ export ไฟล์ excel คุณจะต้องไปเรียกใช้งาน interface
ของ excel มาใช้ เพื่อใช้ในการสร้าง sheet และเขียนข้อมูลลงใน excel

เพิ่มเติมครับ class ที่เป็นจำพวก collection เช่น IDictionary, IList, ICollection, IQueryable,... พวกนี้สามารถใช่ได้ทั้ง
2 แบบนั้นแหละครับ จะ new ใส่ interface หรือ class ก็ไม่ต่างอะไรมาก อาจจะต่างแค่บาง class ครับ เช่น
List<T> กับ IList<T> โดยใน List<T> จะมี method AddRange เพิ่มเข้ามา ส่วน IList<T> จะไม่มี AddRange ครับ
ตรงนี้มันขึ้นอยู่กับการใช้งานต่อด้วยครับ แต่หลักๆ ผมอยากให้คุณเข้าใจหลักการของ interface ก่อนครับ

ขอบคุณที่ช่วยอธิบายเรื่อง interface ครับ จริง ๆ เข้าใจเรื่อง interface แต่ไม่เข้าใจว่าทำไมถึงใช้แบบนั้น สงสัยน่าจะเพราะผมเริ่ม OOP จาก C++ ครับ เลยรู้สึกขัดแย้งกับความรู้สึกในการใช้ แต่ตอนนี้พอจะมองออกแล้วครับว่าทำไม

darktong Mon, 08/10/2018 - 22:13

ผมมาจากฝั่ง java นะครับ ไม่มี class Dictionary เลยจะขอยกตัวอย่างแบบ java แทน ในที่นี้จะเปรียบเทียบระหว่าง

Map<String, Object> map = new HashMap<String, Object>();
HashMap<String, Object> map = new HashMap<String, Object>();

จริงๆแล้วทั้งสองอันนี้เหมือนกันครับ แต่การใช้ interface จะมีข้อได้เปรียบกว่าในกรณีที่มีเราต้องการแก้โค้ดไปใช้ Map ตัวอื่นโดยที่ไม่ break โค้ดเดิมที่มีการใช้งานอยู่ เช่น

private void doSomething(HashMap<String,Object>) {
    // ...
}

doSomething จะต้องส่ง HashMap เข้ามาเป็น parameter เท่านั้น ซึ่งโค้ดก็ทำงานได้ปกติ ทีนี้ในภายหลังเราพบว่าเปลี่ยนไปใช้ TreeMap จะดีกว่า ตรงนี้จะทำให้ doSomething ใช้ไม่ได้ ต้องแก้โค้ดใหม่ ซึ่งในกรณีนี้หากเราใช้ interface แทน

private void doSomething(Map<String,Object>) {
    // ...
}

จะเห็นว่า doSomething ยังคงสามารถทำงานได้ปกติไม่มีปัญหา ซึ่งตรงนี้เราใช้ interface แทนเพื่อให้ code ยืดหยุ่นรองรับความเปลี่ยนแปลงได้ ดังนั้นโดยทั่วไปถ้าเป็นไปได้จะนิยมใช้ interface มากกว่าครับ

ที่ประกาศ​ IDictionary เพื่อจะได้สื่อจุดประสงค์ของ ตัวแปรที่เราจะเรียกใช้งานได้ชัดครับว่า จะใช้งานมันแบบ IDictionary ซึ่งจะมี
Method และ Property ตาม IDictionary ระบุไว้เท่านั้น

แล้วมันก็ช่วยให้เราเขียนโค้ดได้ง่ายด้วย เพราะ Intellisense จะแสดงเฉพาะฟังก์ชันของ IDictionary ซึ่งไม่เยอะ

แต่ถ้าเราประกาศเป็น Dictionary ไปเลย จะมี Method + Property มาอีกเพียบเลยครับ

การประกาศแบบนี้ทำให้เราไม่ทำงานเกิดขอบเขตของตัวแปร และที่สำคัญ โค้ดเราก็ปรับปรุงได้ง่ายกว่า

ถ้าวันนึง Dictionary มันไม่เวิร์ค มี Bug บางอย่างที่ทำให้งานเราส่งมอบไม่ได้ แต่ทางต้นทางเค้ายังไม่ยอมแก้ Class Dictionary ให้เราสักที เราก็สามารถที่จะ Implement IDictionary ขึ้นมาเองแล้วเขียนใหม่ให้ทำงานได้แบบเดิมโดยแก้ไข Bug ไปก่อนก็ยังได้ครับ