“ @private” หมายถึงอะไรใน Objective-C


คำตอบ:


186

มันเป็นตัวแก้ไขการมองเห็น - นั่นหมายความว่าตัวแปรอินสแตนซ์ที่ประกาศว่า@privateสามารถเข้าถึงได้โดยอินสแตนซ์ของคลาสเดียวกันเท่านั้น สมาชิกส่วนตัวไม่สามารถเข้าถึงได้โดยคลาสย่อยหรือคลาสอื่น ๆ

ตัวอย่างเช่น:

@interface MyClass : NSObject
{
    @private
    int someVar;  // Can only be accessed by instances of MyClass

    @public
    int aPublicVar;  // Can be accessed by any object
}
@end

นอกจากนี้เพื่อชี้แจงวิธีการที่เป็นสาธารณะใน Objective-C เสมอ มีวิธีการ "ซ่อน" การประกาศเมธอดอยู่ - ดูคำถามนี้สำหรับข้อมูลเพิ่มเติม


สิ่งที่เกี่ยวกับตัวแปรอินสแตนซ์ที่อยู่ในวงเล็บปีกกาหลังจากการ @implementation หรือไม่ พวกเขาเป็นส่วนตัวตลอดเวลาหรือไม่
John Henckel

ฉันรู้ว่ามันเก่า ... แต่มันไม่ใช่ตัวแก้ไขการมองเห็น มันเป็นตัวดัดแปลงการเข้าถึง มันเป็นความแตกต่างที่สำคัญใน C ++ แต่มันก็มีความแตกต่างใน Objective-C เช่นกัน คอมไพเลอร์สามารถมองเห็นตัวแปรได้ คอมไพเลอร์ไม่อนุญาตให้คุณเข้าถึง
gnasher729

161

ดังที่ htw กล่าวว่าเป็นเครื่องมือแก้ไขการมองเห็น @privateหมายความว่า ivar (ตัวแปรอินสแตนซ์) สามารถเข้าถึงได้โดยตรงจากภายในอินสแตนซ์ของคลาสเดียวกันนั้น อย่างไรก็ตามนั่นอาจไม่ได้มีความหมายอะไรกับคุณมากนักดังนั้นให้ฉันยกตัวอย่างให้คุณ เราจะใช้initวิธีการเรียนเป็นตัวอย่างเพื่อประโยชน์ของความเรียบง่าย ฉันจะแสดงความคิดเห็นแบบอินไลน์เพื่อระบุรายการที่น่าสนใจ

@interface MyFirstClass : NSObject
{
    @public
    int publicNumber;

    @protected  // Protected is the default
    char protectedLetter;

    @private
    BOOL privateBool;
}
@end

@implementation MyFirstClass
- (id)init {
    if (self = [super init]) {
        publicNumber = 3;
        protectedLetter = 'Q';
        privateBool = NO;
    }
    return self;
}
@end

@interface MySecondClass : MyFirstClass  // Note the inheritance
{
    @private
    double secondClassCitizen;
}
@end

@implementation MySecondClass
- (id)init {
    if (self = [super init]) {
        // We can access publicNumber because it's public;
        // ANYONE can access it.
        publicNumber = 5;

        // We can access protectedLetter because it's protected
        // and it is declared by a superclass; @protected variables
        // are available to subclasses.
        protectedLetter = 'z';

        // We can't access privateBool because it's private;
        // only methods of the class that declared privateBool
        // can use it
        privateBool = NO;  // COMPILER ERROR HERE

        // We can access secondClassCitizen directly because we 
        // declared it; even though it's private, we can get it.
        secondClassCitizen = 5.2;  
    }
    return self;
}

@interface SomeOtherClass : NSObject
{
    MySecondClass *other;
}
@end

@implementation SomeOtherClass
- (id)init {
    if (self = [super init]) {
        other = [[MySecondClass alloc] init];

        // Neither MyFirstClass nor MySecondClass provided any 
        // accessor methods, so if we're going to access any ivars
        // we'll have to do it directly, like this:
        other->publicNumber = 42;

        // If we try to use direct access on any other ivars,
        // the compiler won't let us
        other->protectedLetter = 'M';     // COMPILER ERROR HERE
        other->privateBool = YES;         // COMPILER ERROR HERE
        other->secondClassCitizen = 1.2;  // COMPILER ERROR HERE
    }
    return self;
}

ดังนั้นเพื่อตอบคำถามของคุณ @private ปกป้อง ivars จากการเข้าถึงโดยอินสแตนซ์ของคลาสอื่น ๆ โปรดทราบว่า MyFirstClass สองอินสแตนซ์สามารถเข้าถึง ivars ของกันและกันได้โดยตรง สันนิษฐานว่าเป็นเพราะโปรแกรมเมอร์สามารถควบคุมชั้นเรียนนี้ได้โดยตรงเขาจะใช้ความสามารถนี้อย่างชาญฉลาด


20
ควรกล่าวถึงว่าเป็นเรื่องแปลกที่จะใช้ @public, @proteced และ @private ใน Objective-C วิธีการที่ต้องการคือการใช้อุปกรณ์เสริม
Georg Schölly

1
@Georg แต่คุณจะบังคับใช้การเข้าถึงได้อย่างไรถ้าคุณไม่ทำเครื่องหมาย ivars ของคุณด้วยทัศนวิสัยที่ จำกัด
Greg Maletic

5
@Georg Schölly: เนื่องจาก xcode 4.x + วาง@privateเทมเพลตสำหรับวัตถุโดยอัตโนมัติจึงไม่ใช่เรื่องแปลกอีกต่อไป
dawg

1
@Georg ผมคิดว่า @private, @protected สามารถใช้สำหรับกรณีที่มีการถ่ายทอดทางพันธุกรรมมีส่วนเกี่ยวข้องไม่ได้ใช้มันเองแม้ว่า :)
chunkyguy

5
ควรสังเกตว่าวันนี้มีเหตุผลน้อยมากที่จะวางตัวแปรอินสแตนซ์ในส่วนหัวสาธารณะ สามารถวางโดยตรงบน@implementationบล็อก และเมื่อคุณทำเช่นนั้นแล้วพวกเขาจะเป็นส่วนตัวอย่างมีประสิทธิภาพไม่ว่าตัวปรับการมองเห็นจะเป็นใครก็ตาม
BJ Homer

14

สิ่งสำคัญคือต้องเข้าใจความหมายของคำว่าเมื่อมีคนบอกว่าคุณไม่สามารถเข้าถึง@privateตัวแปรอินสแตนซ์ได้ เรื่องจริงคือคอมไพเลอร์จะให้ข้อผิดพลาดถ้าคุณพยายามเข้าถึงตัวแปรเหล่านี้ในซอร์สโค้ดของคุณ ใน GCC และ XCode รุ่นก่อนหน้าคุณจะได้รับคำเตือนแทนข้อผิดพลาด

ไม่ว่าในเวลาใดก็ตามการเดิมพันทั้งหมดจะปิด สิ่งเหล่านี้@privateและไอ@protectedวอรี่สามารถเข้าถึงได้โดยวัตถุของคลาสใด ๆ ตัวดัดแปลงการมองเห็นเหล่านี้ทำให้ยากต่อการรวบรวมซอร์สโค้ดเป็นรหัสเครื่องที่ละเมิดเจตนาของตัวดัดแปลงการมองเห็น

อย่าพึ่งพาตัวดัดแปลงการมองเห็นของ ivar เพื่อความปลอดภัย! พวกเขาไม่ให้เลย พวกเขาอย่างเคร่งครัดสำหรับการรวบรวมเวลาบังคับใช้ตามความต้องการของผู้สร้างคลาส

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.