Objective-C Programming Part IV

Super Self – Initializing

หลังจากเรื่องที่แล้วได้เขียนเกี่ยวกับ Polymorphism ถ้าจะไม่พูดถึง super – self ก็คงจะไม่ครบสักเท่าไหร่

  • super
    เป็น keyword ที่เอาไว้อ้างอิงถึง คลาสที่สืบทอดมา
  • self
    ก็คือเป็นการอ้างอิงถึงตัวเอง

เอาละทีนี้ก็คือว่า มันมีความสำคัญอะไรกับ 2 สิ่งนี้ สำหรับ self กับ super
จริงๆแล้ว self กับ super ส่วนมากจะได้ใช้จริงๆ กับ initial ซะส่วนมาก คือหลังจากการ alloc แล้วเราต้องทำการ init ให้มัน ทีนี้มันก็เกิดปัญหาที่ว่า ถ้าที่เราเขียน class ที่เป็น child จาก parent ที่ต้องการ initial ก่อนใช้งาน แล้วจะทำอย่างไร ?

ตัวอย่าง Code ข้างล่างจะไม่มีปัญหา เพราะว่า Child นั้นไม่ต้องการเขียน method ชื่อ init ดังนั้นก็ไปใช้ของ parent ได้

แบบนี้ก็อาจจะง่าย เวลาใช้งาน ก็อาจจะเขียนประมาณนี้

ก็ตอนนี้ก็เท่ากับว่า ค่า m_age นั้นมีค่าเท่ากับ 12

แต่ถ้าสมมติว่า initial ของ child ต้องการ parameter ด้วย เช่นว่า Children ก็ต้องการให้รับ age ตอน init
และ Student ก็ต้องการให้มี studentID ในตอน init ด้วยละ ดังเช่นตัวอย่าง

เราจะเขียน code ในลักษณะแบบนี้

มันก็จะไปเรียก init ของ child และในตอนนี้ m_studentID ก็มีค่าเท่ากับ 12.00 แล้ว m_age ละ ? เราจะทำการ set ค่า initial สำหรับ parent class ได้อย่างไร ?
เราจะรู้ได้อย่างไรว่า parent class นั้นมี member data อะไรอยู่ในนั้นบ้าง ?
เพราะในขณะนี้เรา overriding ไปแล้ว มันก็เป็นการเรียกใช้ init ของ child โดยไม่ได้เรียก init ของ parent

เพื่อความเข้าใจ ลองมาดูตัวอย่างอีกสักอันกันดีกว่า

แล้วเราก็เขียนในส่วนของ main แบบนี้

ผลจากการ โปรแกรมก็จะได้ว่า

Honda speed: 20

ความจริงแล้วจาก code ข้างบนถ้าทำการ compile มันก็จะไม่แจ้ง error อะไร แต่มันจะแจ้งwarning ออกมา ว่า warning: multiple methods named ‘-init’ found แต่จริงๆแล้วก็ทำงานได้ปกติ เหตุผลทีมันแจ้งแบบนี้ก็เพราะว่า init นั้นเป็น method ของ Object นั่นเอง และเราก็ทำการ Overriding มันไปนั่นเอง ทำให้มันเห็น ว่ามี init อยู่ 2 method

โอเคทีนี้สมมติว่าเรา อาจจะให้มี init กับ initWithSpeed ละ ? ตัวแรกไม่ต้องทำอะไร ส่วนตัวที่สอง ทำการ ใส่ speed เริ่มต้นให้เลย จะเขียนได้แบบไหน เราก็ได้ความคิดว่า งั้น init ก็ไม่ต้องไป Overriding ให้มัน แล้วเราก็เขียน initWithSpeed เพิ่มขึ้นมานั่นเอง โอเค งั้นมาดูเลย

จะเห็นว่า เราก็แค่ เปลี่ยนจาก init ไปเป็น initWithSpeed เท่านั้นเอง งั้นส่วนของ implement นั้นก็ควรจะเป็น

แบบนี้ก็เป็นอันจบ แล้วส่วน main ก็น่าจะเขียนแบบนี้

แต่ความเป็นจริงแล้ว มันไม่ได้ง่ายขนาดนั้น !!!!

ถ้า compile จริงๆมันจะเกิด error ขึ้น เพราะว่า  initWithSpeed นั้น return void  โอเค เราจะแก้ปัญหานี้ได้โดยการเขียน code ใน main แบบนี้

แต่ความจริงแล้ว การแก้ปัญหาแบบนี้มันไม่ค่อยถูกเท่าไหร่ เพราะว่าถ้าจะพิจารณาให้ดีแล้ว มันเหมือนกับเราเขียนว่า initWithSpeed เป็นแค่ function ที่่เรียกใช้หลักจากการสร้าง honda แล้วมากกว่า ถ้าจะสรุปง่ายก็คือว่าการเขียนแบบข้างบน ก็เหมือนกับ การเขียนแบบนี้

เอาละ งั้นเราจะเขียนให้มันใช้ initWithSpeed ร่วมกับ alloc ได้ยังไง

ไม่ยากเลย  เราก็ให้ initWithSpeed ไม่ต้อง return void ให้มัน return Car ออกแทนสิ แต่จะให้มัน return ได้ยังไง นี่คือปัญหา  และ self กับ super จะได้เอามาใช้ตอนนี้เหละ งั้นก็ดูกันเลย

เราทำการเปลี่ยน ในส่วนของ interface ก่อน

โดยเราทำการเปลี่ยนให้ initWithSpeed ทำการ return id ออกมาแทน

และในส่วนของ implementation นั้น จะเขียนได้แบบนี้

จะเห็นว่า เราทำการ เรียกใช้ super และ self

  • [super init]
    ในส่วนนี้เป็นการบอกว่า ให้ เรียกใช้ Class แม่ (super) และทำการ เรียกใช้ init เพราะว่า จริงๆแล้ว Car นั้นสืบทอดมาจาก Object และ init นั้นก็เป็น method ที่เรียกใช้เวลา ทำการ  alloc ตัว object ก็เป็นอันว่า เราได้ทำการ init เรียบร้อยแล้ว ต่อไปก็
  • m_speed = speed
    ตรงนีก็ไม่ได้มีอะไรพิเศษนอกจากทำการ ใส่ค่าให้กับตัวแปร m_speed
  • return self
    ตรงนี้สำคัญเพราะเมื่อเราทำการ initตัวแม่แล้ว และเราก็ทำการ ใส่ค่าให้กับตัวแปรที่ต้องการแล้ว แน่นอนว่า การ alloc นั้น ต้องการขอจอง memory สำหรับตัวมันเอง ไม่ใช่ตัวแม่ ดังนั้นเราก็ return ตัวมันเองออกไป

และทีนี้เราก็จะเขียน main โปรแกรมได้ใหม่ว่า

แบบนี้ก็จะไม่เกิด error หรือ warning ใดๆ เลย และถ้าไม่อยาก initWithSpeed ก็ทำได้เหมือนกัน

ผลจากการ run โปรแกรมก็จะออกมาได้ว่า

Honda speed: 50
Toyota speed: 0

ลองโหลด source ไปลองดูได้ครับ

2 thoughts on “Objective-C Programming Part IV”

  1. แบบนี้ก็อาจจะง่าย เวลาใช้งาน ก็อาจจะเขียนประมาณนี้

    ChildClass* child = [[ChildClass alloc] init:12];
    ก็ตอนนี้ก็เท่ากับว่า ค่า m_age นั้นมีค่าเท่ากับ 12

    ตรงนี้่ผมว่ามัน แปลกๆน้า

  2. code แรก ประกาศ
    @interface Children
    แต่เวลาใช้ทำไม ใช้ ChildClass*
    ChildClass* child = [[ChildClass alloc] init:12];
    ตรงนี้ถูกหรือผิด หรือเปล่าครับ

Leave a Reply