2012-03-22 42 views
27

Tôi đang tạo ứng dụng và tôi có một lớp học với nhiều thuộc tính và tôi đã tự hỏi liệu có thể cung cấp cho họ giá trị mặc định hay không. Bởi vì nếu tôi thực hiện một phương pháp init, đó là rất nhiều công việc phải gõ tất cả mọi thứ, có một cơ hội lớn của typo và nó chỉ là không đẹp mã ...Mục tiêu-C đặt giá trị mặc định cho một thuộc tính

Đây là cách lớp học của tôi trông giống như:

// Goalkeeping attributes 
@property (nonatomic) int aerialAbility; 
@property (nonatomic) int commandOfArea; 
@property (nonatomic) int communication; 
@property (nonatomic) int eccentricity; 
@property (nonatomic) int handling; 
@property (nonatomic) int kicking; 
@property (nonatomic) int oneOnOnes; 
@property (nonatomic) int reflexes; 
@property (nonatomic) int rushingOut; 
@property (nonatomic) int tendencyToPunch; 
@property (nonatomic) int throwing; 

// Technical attributes 
@property (nonatomic) int corners; 
@property (nonatomic) int crossing; 
@property (nonatomic) int dribbling; 
@property (nonatomic) int finishing; 
@property (nonatomic) int firstTouch; 
@property (nonatomic) int freeKickTaking; 
@property (nonatomic) int heading; 
@property (nonatomic) int longShots; 
@property (nonatomic) int longThrows; 
@property (nonatomic) int marking; 
@property (nonatomic) int passing; 
@property (nonatomic) int penaltyTaking; 
@property (nonatomic) int tackling; 
@property (nonatomic) int technique; 

// Mental attributes 
@property (nonatomic) int aggression; 
@property (nonatomic) int anticipation; 
@property (nonatomic) int bravery; 
@property (nonatomic) int composure; 
@property (nonatomic) int concentration; 
@property (nonatomic) int creativity; 
@property (nonatomic) int decisions; 
@property (nonatomic) int determination; 
@property (nonatomic) int flair; 
@property (nonatomic) int influence; 
@property (nonatomic) int offTheBall; 
@property (nonatomic) int positioning; 
@property (nonatomic) int teamwork; 
@property (nonatomic) int workRate; 

// Physical attributes 
@property (nonatomic) int acceleration; 
@property (nonatomic) int agility; 
@property (nonatomic) int balance; 
@property (nonatomic) int jumping; 
@property (nonatomic) int naturalFitness; 
@property (nonatomic) int pace; 
@property (nonatomic) int stamina; 
@property (nonatomic) int strength; 

Vì vậy, sau đó, trong việc thực hiện, tôi đang làm một cái gì đó như:

@synthesize aerialAbility = _aerialAbility; 

Và tôi đã tự hỏi nếu nó sẽ có thể để làm điều này:

@interface MyClass : NSObject 
@property (nonatomic) int someProperty; 

@end 

@implementation MyClass 
@synthesize someProperty = _someProperty = 10; 
@end 

Tôi biết điều này sẽ không hoạt động, và điều này không đúng chút nào, nhưng tôi đã tự hỏi liệu có cách nào để làm điều gì đó như thế này không.

Giống như trong java bạn có thể:

class MyClass 
{ 
private int someProperty = 10; 
public int getSomeProperty(){return someProperty;} 
public void setSomeProperty(int someProperty){this.someProperty = someProperty;} 
} 

Trả lời

39

Tôi chưa bao giờ thấy hành vi này trước đây nhưng tôi khá chắc chắn đây là những gì các bước init là khi phân bổ một đối tượng, đó là thiết lập các biến và khởi tạo vật.

-(id)init { 
    if (self = [super init]) { 
     self.someProperty = 10; 
    } 
    return self; 
} 

Và gọi nó như thế này:

MyClass* test = [[MyClass alloc] init]; 

Chú ý rằng bạn có thể có nhiều hơn một hàm init cho phép bạn có một vài bộ khác nhau của các giá trị mặc định.

Những gì @synthesize làm là báo cho trình biên dịch trước rằng nó sẽ tạo mã cho bộ/nhận, không đặt giá trị của thuộc tính. '=' Chỉ nói với trình hoàn thiện rằng, mặc dù tên của biến và thuộc tính không giống nhau, nhưng chúng phải được kết nối.

Ngoài ra, dưới dạng ý kiến ​​cá nhân (không được đề cập đến câu hỏi), đối tượng này có vẻ như to lớn và bạn có thể chia nhỏ nó theo một cách nào đó hoặc làm như người khác được đề xuất. Có lẽ lớp này có thể kế thừa từ một vài lớp khác để cung cấp cho nó những đặc tính khác nhau mà nó cần? một gợi ý vì tôi không biết mã khác của bạn trông như thế nào :)

+1

Đúng vậy - initializer là phạt tiền nơi để thiết lập giá trị ban đầu cho một ivar hoặc tài sản. Cụ thể hơn, initializer được chỉ định (initializer mà bất kỳ initializer khác cho lớp sẽ gọi) là một trong những nơi bạn nên thiết lập các giá trị đó. – Caleb

+0

Cảm ơn các đề xuất, tuy nhiên, tôi đang cố gắng tránh đặt 30+ bài tập trong trình khởi tạo và lớp học không thể chia ra được (dĩ nhiên, nó luôn có thể, nhưng nó sẽ làm cho thiết kế lớp của tôi tồi tệ hơn). –

+0

tại sao muốn tránh điều đó tôi không nhận được. Các init được thực hiện cho mục đích này, hoặc bạn có thể sử dụng một từ điển mà bạn sẽ phải thiết lập trong init anyway ... – chikuba

9

Đối với một số lượng lớn thuộc tính như vậy, tôi muốn lưu trữ dữ liệu dưới dạng từ điển chứ không phải thuộc tính cá nhân và tôi sẽ lưu trữ các giá trị mặc định trong danh sách thuộc tính: NSDictionary đối tượng có thể được khởi tạo bằng một quảng cáo danh sách rty dễ dàng.

Nếu sử dụng từ điển không theo sở thích của bạn, tôi vẫn lưu trữ các giá trị mặc định trong danh sách thuộc tính và trong trình khởi tạo được chỉ định, tôi sẽ lặp lại các mục trong danh sách thuộc tính và áp dụng chúng vào self bằng cách sử dụng khóa- mã hóa giá trị. Bạn nên lưu ý rằng điều này chỉ thích hợp cho dữ liệu đáng tin cậy, không phải dữ liệu do người dùng cung cấp, vì nó có thể bị tấn công để thiết lập các thuộc tính khác mà bạn không mong đợi.

+1

+1 và từ điển cũng sẽ dễ mở rộng và thay đổi sau này. –

+0

Nhưng nếu bạn muốn lưu trữ các thuộc tính loại hỗn hợp trong từ điển thì sao? – To1ne

+0

@ To1ne Đó không phải là vấn đề. NSDictionary không thực thi an toàn loại. Bạn có thể lưu trữ nhiều loại đối tượng. – mtmurdock

4

Không có built-in cách Java như khởi tạo thuộc tính tổng hợp hoặc ivars trong Objective C. Tuy nhiên, vì tính chất của bạn trông gần như giống hệt nhau, bạn có thể muốn xem xét việc làm cho chúng @dynamic thay vì tổng hợp chúng.Để chắc chắn, bạn sẽ cần phải viết hai phương pháp đáng sợ (here is a nice and clean example cho bạn), nhưng đổi lại bạn sẽ có được một cách thống nhất để lưu trữ các thuộc tính của bạn dưới dạng các đối tượng bên trong NSMutableDictionary. Điều này mở ra một số lựa chọn thay thế thú vị không có sẵn với các màu trắng đơn giản: bạn có thể hoãn khởi tạo các thuộc tính của mình cho đến khi cần thiết, bạn có thể cung cấp giá trị mặc định cho các thuộc tính chưa được đặt hoặc bạn có thể khởi tạo thuộc tính của mình "bán buôn" bằng cách điền từ điển giá trị cho khóa của chúng.

+0

Có vẻ thú vị, tôi sẽ xem xét vào ngày mai, cảm ơn! –

0

Đề xuất từ ​​điển ở trên là một gợi ý tốt. Đôi khi tôi đã sử dụng các đối tượng cấu hình chuyên dụng:

@interface GoalKeepingAttributes 
@property (nonatomic) int agression 
@property (nonatomic) int ... etc 
@end 

@implementation GoalKeepingAttributes 
@end 

vv. Nếu cần, lớp này có thể có phương thức init đặt một loạt giá trị và mặc định.

Bạn cũng có thể sử dụng cấu trúc kiểu c, vì đây chỉ là nguyên thủy.

Đúng là điều này được chỉ trì hoãn vấn đề, di chuyển khởi từ nhóm này sang nhóm lớp cấu hình, nhưng:

  • bạn phải làm điều này với một cuốn từ điển nào
  • bạn có thể bình luận các thiết lập cấu hình
  • chiến thắng lớn nhất: lớp cấu hình được đánh máy mạnh mẽ, mà bắt lỗi lúc biên dịch, cho phép hoàn thành mã xcode

Bạn có thể chia ra các cấu hình thành các loại khác nhau (Goalkeeping, Technical và Mental). Một lần nữa, nó chỉ chia nhỏ vấn đề, nhưng điều đó có thể giúp giữ cho mọi thứ tập trung.

0

Một khả năng khác sẽ là ghi đè các getters mặc định cho các thuộc tính. Trong getters của bạn, bạn có thể xem để xem các giá trị đã được khởi tạo và, nếu không, trả về giá trị mặc định của bạn. (Điều đó sẽ làm việc cho một số loại tài sản nhưng không phải cho người khác, rõ ràng - bạn cần giá trị mặc định là một chỉ ra rằng không có giá trị đã được thiết lập.)

0
- (id)init 
{ 
    self = [super init]; 
    if (self != nil) { 
     [self commonInit]; 
    } 

    return self; 
} 

- (id)initWithFrame:(CGRect)frame 
{ 
    self = [super initWithFrame:frame]; 
    if (self != nil) { 
     [self commonInit]; 
    } 

    return self; 
} 

-(instancetype)initWithCoder:(NSCoder *)aDecoder { //nib init 
    self = [super initWithCoder:aDecoder]; 
    if (self != nil) { 
     [self commonInit]; 
    } 
    return self; 
} 

Bạn có thể thiết lập giá trị mặc định và làm luận mặc định trong commonInit nếu đối tượng là một khung nhìn. Nếu nó không xem, bạn có thể làm điều đó trong hàm init theo ý kiến ​​của tôi.

0

Có, bạn có thể ghi đè getter trong trường hợp để đặt giá trị mặc định trước khi thuộc tính được inited.

Ví dụ, xác định tài sản trong file .h:

@interface MySegmentedControl : UISegmentedControl 
@property (assign, nonatomic) CGFloat systemFontOfSize; 
@end 

và ghi đè phương thức getter và thiết lập giá trị mặc định đang được triển khai trong file .m:

@implementation MySegmentedControl  
-(CGFloat) systemFontOfSize 
{ 
    return _systemFontOfSize ? _systemFontOfSize : 17.0f; 
}  
@end 
Các vấn đề liên quan