รับทําเว็บไซต์ รับทําseo
 
รับทําเว็บไซต์ รับทําseo
บทความที่น่าสนใจ

บทความ ที่น่าสนใจ

Objective-C : Copying Object (ตอนที่1)

    Copying Object

    ในบทนี้เราจะว่าด้วยเรื่องของการ copy object หรือการคัดลอกข้อมูลระหว่างอ็อบเจ็ก และคอนเซ็ปของการ copy ต่างๆเช่น shallow copy และ deep copy และวิธีการก๊อบปี้อ็อบเจ็กของคลาสต่างๆใน Foundation Framework
    โดยปกติเมื่อเราประกาศตัวแปรที่เป็น primitive type เช่น int , double การที่เราจะก๊อบปี้ข้อมูลทำได้ง่ายมากเพียงแค่ใช้เครื่องหมาย = ก็สามารถคัดลอกข้อมูลได้แล้ว ดังตัวอย่างโค้ดต่อไปนี้

     

        int x = 10;
        int y;
     
        y = x;
     
        x = x + 20;
        y = y + 30;
     
        NSLog(@"x: %d y: %d", x, y);

     

    กำหนดให้ตัวแปร x มีค่าเท่ากับ 10 หลังจากนั้น y ก็ก๊อบปี้ค่าตัวแปร x เพื่อให้ตัวแปรทั้งสองมีค่าเท่ากัน จากนั้นบวกค่าให้กับตัวแปร x ด้วย 20 ส่วนตัวแปร y บวกด้วย 30 เมื่อบวกด้วยคนละค่ากัน แน่นอนว่าตัวแปรทั้งสองย่อมมีค่าไม่เท่ากัน เห็นได้ชัดว่าตัวแปร x และ y นั้นไม่ได้มีผลกระทบอะไรต่อกัน การเปลี่ยนแปลงค่า x ไม่ได้เกี่ยวข้องกับค่า y และในทางกลับกันค่า y ก็ไม่ได้เกี่ยวข้องกับค่า x แต่ประการใด ลองพิจารณาโปรแกรมตัวอย่างต่อไปนี้

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    
    #import <Foundation/Foundation.h>
     
    int main(int argc, const char * argv[])
    {
     
        @autoreleasepool {
     
            NSMutableString *hello = [[NSMutableString alloc] initWithString:@"Hello"];
            NSMutableString *temp;
     
            temp = hello ;
     
            [temp appendString:@" World"];
     
            NSLog(@"%@", hello ) ;
            NSLog(@"%@", temp ) ;
        }
        return 0;
    }

     

    โค้ดของโปรแกรมได้ประกาศสองตัวคือตัวแปร hello และ temp ซึ่งได้กำหนดค่าเริ่มต้นให้เท่ากับ “Hello” จากนั้นเราได้ให้ค่า temp = hello ดังนั้นค่าตัวแปร temp ก็ควรจะมีเท่ากับ “Hello” และในบรรทัดต่อมาเราได้เปลี่ยนแปลงค่าของ temp ด้วยการนำสตริง “ World” มาต่อท้าย เมื่อเราแสดงค่าของตัวแปรด้วย NSLog ก็จะได้ผลลัพธ์ดังนี้

     

    Program Output

    Hello World
    Hello World

     

    จากผลลัพธ์ของโปรแกรมแสดงให้เห็นว่าตัวแปร hello และ temp นั้นต่างก็เป็นคำว่า Hello World ทั้งๆที่เราไม่ได้ไปแก้ไข hello เลยสักนิด ทำไมถึงเป็นแบบนี้ ? ในความเป็นจริงแล้วสิ่งที่เราได้ทำก็คือประกาศตัวแปรที่เป็น class instance หรือ object นั้นเป็นแบบ pointer ฉะนั้นแล้วการเขียนโค้ด

     

            temp = hello ;

     

    เป็นการก๊อบปี้ตำแหน่งหน่วยความจำ (Memory Address) หรือพูดอีกอย่างว่าให้ temp ชี้ไปยังตำแหน่งเดียวกันกับ hello

     

    เมื่อเป็นตำแหน่งเดียวกัน การแก้ไขตัวแปร temp ย่อมเท่ากับแก้ไข hello เช่นเดียวกัน โปรแกรมตัวอย่างแสดงให้เห็นว่าเราไม่สามารถที่จะใช้เครื่องหมาย = ในการก๊อบปี้ได้ แล้วเราจะก๊อบปี้อ็อบเจ็กได้อย่างไร

     

    copy and mutable copy

    ปัญหาที่เกิดขึ้นสามารถแก้ไขได้ด้วยการใช้เมธอดก๊อบปี้ที่มีอยู่แล้วของ Foudation Class ซึ่งมีด้วยกันสองเมธอดคือ copy และ mutableCopy สองเมธอดนี้ต่างกันตรงที่ ถ้าเราต้องการจะก๊อบปี้แล้วให้อ็อบเจ็กนั้นสามารถแก้ไขค่าต่างได้ ก็ต้องใช้ mutableCopy เพราะเมธอดนี้จะสร้างอ็อบเจ็กที่เป็นแบบ mutable นั่นเอง

     

    Program 12.1

    main.m

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    
    #import <Foundation/Foundation.h>
     
    int main(int argc, const char * argv[])
    {
     
        @autoreleasepool {
     
            NSMutableString *hello = [[NSMutableString alloc] initWithString:@"Hello"];
            NSMutableString *temp;
     
            temp = [hello mutableCopy];
     
            [temp appendString:@" World"];
     
            NSLog(@"%@", hello ) ;
            NSLog(@"%@", temp ) ;
     
            [temp release];
        }
        return 0;
    }

     

    Program 12.1 Output

    Hello
    Hello World

     

    เมื่อคอมไพล์และให้โปรแกรมทำงานก็จะเห็นว่าผลลัพธ์นั้นแตกต่างกับโปรแกรม แรก ตัวแปร hello และ temp ต่างเป็นอิสระต่อกัน เพราะการใช้เมธอด mutableCopy หรือ copy นั้นจะเป็นการสร้างอ็อบเจ็กใหม่โดยมีข้อมูลเหมือนกับตัวต้นแบบ เมื่อเป็นคนละอ็อบเจ็กการเปลี่ยนแปลงค่าของตัวแปรทั้งสองจึงไม่เกี่ยวข้อง กัน

     

    พิจารณาตัวอย่างโปรแกรมง่ายๆต่อไปนี้อีกสักโปรแกรม เพื่อทำความเข้าใจเกี่ยวกับการก๊อบปี้อ็อบเจ็กมากขึ้น

     

    Program 12.2

    main.m

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    
    #import <Foundation/Foundation.h>
     
    int main(int argc, const char * argv[])
    {
     
        @autoreleasepool
        {
            NSMutableString* apple = [NSMutableString stringWithString:@"Apple"];
            NSMutableString* mango = [NSMutableString stringWithString:@"Mango"];
            NSMutableString* orange = [NSMutableString stringWithString:@"Orange"];
     
            NSMutableArray* fruits_B = [NSMutableArray arrayWithObjects:apple
                                        ,mango,orange, nil];
     
            NSArray* fruits_A = [fruits_B copy];
     
            [fruits_B removeLastObject];
     
            NSLog(@"B: %@",fruits_B);
            NSLog(@"A: %@",fruits_A);
     
            [fruits_A release];
     
        }
        return 0;
    }

     

    Program 12.2 Output

    B: (
        Apple,
        Mango
    )

    A: (
        Apple,
        Mango,
        Orange
    )

     

    จากโปรแกรมเราได้สร้างอาเรย์ fruits_B ซึ่งประกอบไปด้วย Apple Mango Organge ตามลำดับ จากนั้นเราสร้าง fruits_A ด้วยการก๊อบปี้ fruits_B ตอนนี้อาเรย์ทั้งสองตัวมีสมาชิกเหมือนกัน แต่เมื่อถึงบรรทัดที่ 18 เราได้ลบสมาชิกตัวท้ายสุดของ fruits_B ไป ดังนั้นผลลัพธ์จึงได้ดัง Output ที่แสดงออกมา จะเห็นว่า A และ B มีสมาชิกไม่เท่ากัน เราจะลองพิจารณาโปรแกรมอีกสักหนึ่งโปรแกรมโดยการแก้ไขโค้ดของโปรแกรม 12.2 ให้เป็นดังนี้

     

    Program 12.3

    main.m

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    
    #import <Foundation/Foundation.h>
     
    int main(int argc, const char * argv[])
    {
     
        @autoreleasepool {
     
            NSMutableString* apple = [NSMutableString stringWithString:@"Apple"];
            NSMutableString* mango = [NSMutableString stringWithString:@"Mango"];
            NSMutableString* orange = [NSMutableString stringWithString:@"Orange"];
     
            NSMutableArray* fruits_B = [NSMutableArray arrayWithObjects:apple
                                        ,mango,orange, nil];
     
            NSArray* fruits_A = [fruits_B copy];
     
            [[fruits_B objectAtIndex:0] appendString:@"123"];
     
            NSLog(@"B: %@",fruits_B);
            NSLog(@"A: %@",fruits_A);
     
            [fruits_A release];
     
        }
        return 0;
    }

     

    เราแก้ไขโค้ดเปลี่ยนโค้ดบรรทัดที่ 18 ของโปรแกรม โดยนำสตริง 123 มาต่อท้ายอ็อบเจ็กแรกในอาเรย์ fruits_B ซึ่งนั่นก็คือ “Apple” ดังนั้นเมื่อเราให้แสดงค่าของตัวแปร B จึงควรจะเป็น Apple123 , Mango , Orange แต่ผลลัพธ์ที่ได้กลับเป็นดังนี้

     

    Program 12.3 Output

    B: (
        Apple123,
        Mango,
        Orange
    )

    A: (
        Apple123,
        Mango,
        Orange
    )

     

    แน่นอนว่าค่า fruits_B แสดงออกมาได้ถูกต้องตามที่ได้คาดคิดไว้ แต่สิ่งที่ตามก็คือ Apple ใน fruits_A กลายเป็น Apple123 เหมือนกับ fruits_B เหตุใดจึงเป็นเช่นนี้ ? ทั้งๆที่เราก็ได้เมธอด copy ดังนั้นตัวแปร fruits_A และ fruits_B ก็น่าจะเป็นคนตัวกัน แต่เมื่อแก้ไขสมาชิกของอาร์เรย์ fruit_B กลับส่งผลกระทบต่อสมาชิกใน fruit_A

     

     

บทความที่น่าสนใจ

บทความ ล่าสุด

บทความ ความรู้ด้านไอที, คอมพิวเตอร์ Techonlogy, Gadget, ความรู้เกี่ยวกับคอมพิวเตอร์ กับทาง SoftMelt.com