Kế thừa Objective-C

Một trong những khái niệm quan trọng nhất trong lập trình hướng đối tượng là tính kế thừa. Tính kế thừa cho phép chúng ta định nghĩa một lớp theo nghĩa của một lớp khác, giúp tạo và duy trì một ứng dụng dễ dàng hơn. Điều này cũng tạo cơ hội để sử dụng lại chức năng mã và thời gian thực hiện nhanh chóng.

Khi tạo một lớp, thay vì viết các thành viên dữ liệu hoàn toàn mới và các hàm thành viên, lập trình viên có thể chỉ định rằng lớp mới sẽ kế thừa các thành viên của một lớp hiện có. Lớp hiện có này được gọi làbase lớp và lớp mới được gọi là derived lớp học.

Ý tưởng kế thừa thực hiện is amối quan hệ. Ví dụ, IS-A động vật có vú, IS-A động vật có vú, chó IS-A động vật, do đó chó IS-A động vật cũng như vậy.

Các lớp cơ sở & có nguồn gốc

Objective-C chỉ cho phép kế thừa đa cấp, tức là nó có thể chỉ có một lớp cơ sở nhưng cho phép kế thừa đa cấp. Tất cả các lớp trong Objective-C đều có nguồn gốc từ lớp chaNSObject.

@interface derived-class: base-class

Xem xét một lớp cơ sở Person và lớp dẫn xuất của nó Employee như sau -

#import <Foundation/Foundation.h>
 
@interface Person : NSObject {
   NSString *personName;
   NSInteger personAge;
}

- (id)initWithName:(NSString *)name andAge:(NSInteger)age;
- (void)print;

@end

@implementation Person

- (id)initWithName:(NSString *)name andAge:(NSInteger)age {
   personName = name;
   personAge = age;
   return self;
}

- (void)print {
   NSLog(@"Name: %@", personName);
   NSLog(@"Age: %ld", personAge);
}

@end

@interface Employee : Person {
   NSString *employeeEducation;
}

- (id)initWithName:(NSString *)name andAge:(NSInteger)age 
  andEducation:(NSString *)education;
- (void)print;
@end

@implementation Employee

- (id)initWithName:(NSString *)name andAge:(NSInteger)age 
   andEducation: (NSString *)education {
      personName = name;
      personAge = age;
      employeeEducation = education;
      return self;
   }

- (void)print {
   NSLog(@"Name: %@", personName);
   NSLog(@"Age: %ld", personAge);
   NSLog(@"Education: %@", employeeEducation);
}

@end

int main(int argc, const char * argv[]) {
   NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];        
   NSLog(@"Base class Person Object");
   Person *person = [[Person alloc]initWithName:@"Raj" andAge:5];
   [person print];
   NSLog(@"Inherited Class Employee Object");
   Employee *employee = [[Employee alloc]initWithName:@"Raj" 
   andAge:5 andEducation:@"MBA"];
   [employee print];        
   [pool drain];
   return 0;
}

Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:

2013-09-22 21:20:09.842 Inheritance[349:303] Base class Person Object
2013-09-22 21:20:09.844 Inheritance[349:303] Name: Raj
2013-09-22 21:20:09.844 Inheritance[349:303] Age: 5
2013-09-22 21:20:09.845 Inheritance[349:303] Inherited Class Employee Object
2013-09-22 21:20:09.845 Inheritance[349:303] Name: Raj
2013-09-22 21:20:09.846 Inheritance[349:303] Age: 5
2013-09-22 21:20:09.846 Inheritance[349:303] Education: MBA

Kiểm soát truy cập và kế thừa

Một lớp dẫn xuất có thể truy cập tất cả các thành viên riêng của lớp cơ sở của nó nếu nó được định nghĩa trong lớp giao diện, nhưng nó không thể truy cập các thành viên riêng được xác định trong tệp thực thi.

Chúng tôi có thể tóm tắt các kiểu truy cập khác nhau tùy theo người có thể truy cập chúng theo cách sau:

Một lớp dẫn xuất kế thừa tất cả các phương thức và biến của lớp cơ sở với các ngoại lệ sau:

  • Không thể truy cập các biến được khai báo trong tệp triển khai với sự trợ giúp của phần mở rộng.

  • Không thể truy cập các phương thức được khai báo trong tệp triển khai với sự trợ giúp của phần mở rộng.

  • Trong trường hợp lớp kế thừa thực thi phương thức trong lớp cơ sở, thì phương thức trong lớp dẫn xuất được thực thi.