MST

星途 面试题库

面试题:Objective-C 代码规范中的类设计原则

在 Objective-C 代码规范中,类的设计要遵循单一职责原则。请以一个简单的 iOS 应用场景为例,说明如何通过类的设计遵循这一原则,提高代码的可维护性。同时,谈谈在类的继承体系设计中,如何避免违反开闭原则,举例说明。
19.0万 热度难度
编程语言Objective-C

知识考点

AI 面试

面试题答案

一键面试

1. 遵循单一职责原则提高代码可维护性

假设我们要开发一个简单的 iOS 待办事项应用,有展示待办事项列表和添加待办事项功能。

  • 不遵循单一职责原则的设计
// 这个类试图处理展示和添加待办事项,职责不单一
@interface TodoManager : NSObject
- (void)displayTodos;
- (void)addTodo:(NSString *)todo;
@end

@implementation TodoManager
- (void)displayTodos {
    // 展示待办事项逻辑
}
- (void)addTodo:(NSString *)todo {
    // 添加待办事项逻辑
}
@end

这种设计下,如果展示逻辑或添加逻辑发生变化,可能会影响到另一个功能,可维护性较差。

  • 遵循单一职责原则的设计
// 负责展示待办事项列表
@interface TodoDisplay : NSObject
- (void)displayTodos;
@end

@implementation TodoDisplay
- (void)displayTodos {
    // 展示待办事项逻辑
}
@end

// 负责添加待办事项
@interface TodoAdder : NSObject
- (void)addTodo:(NSString *)todo;
@end

@implementation TodoAdder
- (void)addTodo:(NSString *)todo {
    // 添加待办事项逻辑
}
@end

这样,当展示逻辑改变时,只需要修改 TodoDisplay 类,添加逻辑改变时,只修改 TodoAdder 类,提高了代码的可维护性。

2. 在类的继承体系设计中避免违反开闭原则

开闭原则指软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。

  • 违反开闭原则的例子
// 图形类
@interface Shape : NSObject
- (CGFloat)area;
@end

@implementation Shape
- (CGFloat)area {
    return 0;
}
@end

// 圆形类继承自图形类
@interface Circle : Shape
@property (nonatomic, assign) CGFloat radius;
- (instancetype)initWithRadius:(CGFloat)radius;
@end

@implementation Circle
- (instancetype)initWithRadius:(CGFloat)radius {
    self = [super init];
    if (self) {
        _radius = radius;
    }
    return self;
}
- (CGFloat)area {
    return M_PI * self.radius * self.radius;
}
@end

// 假设现在要添加矩形类,如果在 Shape 类中直接修改添加新逻辑来处理矩形计算面积,就违反了开闭原则
@interface Rectangle : Shape
@property (nonatomic, assign) CGFloat width;
@property (nonatomic, assign) CGFloat height;
- (instancetype)initWithWidth:(CGFloat)width height:(CGFloat)height;
@end

@implementation Rectangle
- (instancetype)initWithWidth:(CGFloat)width height:(CGFloat)height {
    self = [super init];
    if (self) {
        _width = width;
        _height = height;
    }
    return self;
}
- (CGFloat)area {
    return self.width * self.height;
}
@end

这里如果在 Shape 类中为了适应矩形添加新逻辑,就修改了 Shape 类,违反了开闭原则。

  • 遵循开闭原则的做法
// 图形类,定义抽象方法
@interface Shape : NSObject
- (CGFloat)area;
@end

@implementation Shape
- (CGFloat)area {
    // 这里可以抛出异常或者做默认处理,实际应用中具体分析
    @throw [NSException exceptionWithName:@"UnimplementedAreaCalculation" reason:@"Subclasses should implement area calculation" userInfo:nil];
}
@end

// 圆形类继承自图形类
@interface Circle : Shape
@property (nonatomic, assign) CGFloat radius;
- (instancetype)initWithRadius:(CGFloat)radius;
@end

@implementation Circle
- (instancetype)initWithRadius:(CGFloat)radius {
    self = [super init];
    if (self) {
        _radius = radius;
    }
    return self;
}
- (CGFloat)area {
    return M_PI * self.radius * self.radius;
}
@end

// 矩形类继承自图形类
@interface Rectangle : Shape
@property (nonatomic, assign) CGFloat width;
@property (nonatomic, assign) CGFloat height;
- (instancetype)initWithWidth:(CGFloat)width height:(CGFloat)height;
@end

@implementation Rectangle
- (instancetype)initWithWidth:(CGFloat)width height:(CGFloat)height {
    self = [super init];
    if (self) {
        _width = width;
        _height = height;
    }
    return self;
}
- (CGFloat)area {
    return self.width * self.height;
}
@end

这种情况下,当添加新的图形类(如矩形)时,不需要修改 Shape 类,只需要扩展新的子类并实现相应的 area 方法,遵循了开闭原则。