【OC】OC类和对象下学习(分点)

前置声明,由于笔者学习过c++语言,因此文章中部分知识点会与c++做类比,方便同样学过c++语言的童鞋来学习

1. == 和isEqual(简单)

== :
基本类型变量,直接比较值是否相等,如:65 == 65.0f==‘A’
对象类型:必须是同一对象才相等,即地址相等就相等
isEqual :
isEqual是NSObject的类方法,因此所有的OC类都有这个方法,库提供的原始功能和==没有区别,因此如果我们有特殊需要,可以 重写isEqual类方法
例如:让两个不同类对象,但是里面包含字符串相同,就让他们是相等的.

2. 强制类型转换

在 Objective-C 中,有类型转换的概念,但它与其他编程语言中的强制类型转换有所不同。Objective-C 中的类型转换通常涉及到对象指针之间的转换,而不是基本数据类型之间的转换。

类型转换在 Objective-C 中主要涉及两个操作:

  1. 隐式类型转换(Implicit Type Conversion):这种类型转换是由编译器自动处理的,通常涉及到父类指针和子类指针之间的转换,例如,将子类对象赋值给父类指针。

    ParentClass *parentObj = [[ChildClass alloc] init];
    

    在这个示例中,ChildClass 的实例对象被分配给了 ParentClass 类型的指针,这是一种隐式类型转换。

即父类的指针类型变量,是可以指向子类对象的,这是多态性的体现

  1. 显式类型转换(Explicit Type Conversion):Objective-C 不提供像C或C++中的强制类型转换操作符,但你可以使用类型转换函数来执行显式类型转换。最常用的是使用 idas 关键字来进行类型转换。

    ChildClass *childObj = (ChildClass *)parentObj;
    

    这是一种显式类型转换,其中 parentObjParentClass 类型的指针,通过强制类型转换,它被转换为 ChildClass 类型的指针。

需要谨慎使用显式类型转换,因为它们可能引入运行时错误,特别是如果类型转换不正确或不合理。通常情况下,在 Objective-C 中,隐式类型转换和多态性(子类对象赋值给父类指针)更常见和安全。

3. 多态

多态(Polymorphism)是面向对象编程中的一个重要概念,它允许不同的对象以相同的方式对待,从而提高了代码的通用性和可扩展性。多态性允许你使用父类的指针或引用来引用子类的对象,并在运行时确定要调用哪个方法。这意味着不同类型的对象可以响应相同的消息(方法调用),但可能会以不同的方式做出反应。

在 Objective-C 中,多态性的实现涉及以下几个要点:

  1. 继承:多态性是通过继承实现的。子类继承了父类的接口和行为,因此可以替代父类对象。

  2. 方法重写:子类可以重写(覆盖)父类的方法,以提供自己的实现。重写后,子类方法将覆盖父类方法,但必须具有相同的方法签名。

  3. 父类指针指向子类对象:在 Objective-C 中,你可以使用父类的指针或引用来引用子类的对象。这意味着你可以将一个子类对象分配给一个父类指针,以便以通用方式处理不同类型的对象。

下面是一个示例,展示了多态性在 Objective-C 中的应用:

@interface Shape : NSObject

- (void)draw;

@end

@implementation Shape

- (void)draw {
    NSLog(@"Drawing a generic shape");
}

@end

@interface Circle : Shape

- (void)draw;

@end

@implementation Circle

- (void)draw {
    NSLog(@"Drawing a circle");
}

@end

@interface Rectangle : Shape

- (void)draw;

@end

@implementation Rectangle

- (void)draw {
    NSLog(@"Drawing a rectangle");
}

@end

在这个示例中,Shape 是一个抽象基类,定义了一个 draw 方法。CircleRectangle 分别是 Shape 的子类,并重写了 draw 方法。

现在,你可以使用多态性来处理不同类型的图形对象:

Shape *shape1 = [[Circle alloc] init];
Shape *shape2 = [[Rectangle alloc] init];

[shape1 draw]; // 调用 Circle 类的 draw 方法
[shape2 draw]; // 调用 Rectangle 类的 draw 方法

即使 shape1shape2 的静态类型是 Shape,它们指向的实际对象是 CircleRectangle,因此在运行时会分别调用相应的重写方法。

这就是多态性的核心概念:通过使用父类指针引用不同子类对象,根据对象的实际类型来调用方法,而无需关心对象的具体类型。这使代码更加通用和灵活。

4.NSString类,重写了isEqual和isEqualToString方法,都可以用来比较两个字符串的字符序列是否相等,但第二个是专门用来比较字符串的

5.选择定义一个父类作为抽象类,这系列类外面称为一个类族

6.类别

  1. 了解语法格式
  2. 用于动态为现有类添加方法(通常只添加方法),并且不需要创建子类,不需要访问原有类的源代码
  3. 类别实现部分的文件名通常命名为:"类别+类别名.m"的形式.使用时记得包上该.h文件
  4. 建议:使用时,虽然类别可以重写原有类中的方法,但通常不推荐这么做,如果你需要重写原有类的方法,更好的建议是通过原有类派生子类,然后再子类中重写父类原有的方法
  5. 两点说明:
    1)使用类别添加新方法,会影响 该类及其子类
    2)可根据需要为一个类定义多个类别,不同的类别都可对原有的类增加方法定义
  6. 三种用法:
    1)用类别对类进行模块化设计:
    简单说就是,A类多弄几个类别B,C,D.然后这个类就可以提供A.m , A+B.m , A+C.m等实现文件了.通过这种方式就可以对类实现按模块分布到不同的*.m文件中,从而提高项目后期的可维护性
    2)用类别来调用私有方法:
    其实就是,如果一个方法在接口部分未声明,只在实现部分实现,那么这个方法是私有的无法正常访问,但是通过类别将这个方法添加到类中,这个方法就可以正常调用了.没啥难的
    3)用类别实现非正式协议:
  7. 方法的可见性:
    如果我在类别中定义的方法,是原本类中有的,(相当于重写),那么就是直接沿用原本类中方法的访问权限,如果是原本类中没有的方法,自己可以设定访问权限,默认是公开的,对吧

XCode中 : command+鼠标右键,可点进该类的头文件

7.类别官方讲法:

在 Objective-C 中,类别(Category)是一种非常有用的机制,它允许你将方法添加到现有的类中,而不需要修改类的原始源代码。类别提供了一种扩展类功能的方式,使你可以将相关的方法组织在一起,从而更容易管理和维护代码。

以下是类别的一些关键概念和使用方法:

  1. 类别的声明:类别声明类似于类的接口部分,但在类名后加上括号中的类别名称。类别声明通常包含一组方法的声明,没有成员变量。例如:

    @interface ClassName (CategoryName)
    
    - (void)newMethod;
    
    @end
    
  2. 类别的实现:类别的实现与类的实现部分类似,包含了类别中方法的实际实现。例如:

    @implementation ClassName (CategoryName)
    
    - (void)newMethod {
        // 方法实现
    }
    
    @end
    
  3. 使用类别:要使用类别中的方法,你只需将类别添加到类的实现中。你可以在类的实现部分的任何地方添加类别,而不需要修改原始类的代码。例如:

    #import "ClassName+CategoryName.h"
    
    @implementation ClassName
    
    // 现在可以使用 CategoryName 中定义的 newMethod
    
    @end
    
  4. 方法覆盖:如果类别中的方法名称与原始类中的方法名称相同,类别中的方法将覆盖原始类中的方法。这允许你修改现有类的行为或添加新的行为。

  5. 无法添加实例变量:类别不能添加新的实例变量(成员变量),因为这将违反类的封装性。类别只能添加方法。

  6. 通常用途:类别通常用于将一个大类拆分成多个更小的类别,以提高代码的可维护性。例如,你可以创建一个类别来添加与界面相关的方法,另一个类别用于数据处理,等等。这有助于将类分解为更小的模块,使代码更易于管理。

  7. 避免命名冲突:当你扩展系统类时,要特别小心,以避免与系统类或其他类别发生方法名冲突。最好使用唯一的类别名称,以降低冲突的风险。

类别是 Objective-C 中强大的代码组织工具,它允许你以模块化的方式组织和扩展现有的类,从而使代码更具可读性和可维护性。这使得 Objective-C 成为一个非常灵活的编程语言。

7. 扩展 : 相当于匿名类别

扩展(Extension)是 Objective-C 中的一种机制,用于向类中添加额外的实例变量和私有方法,通常用于类的内部实现细节。与类别不同,扩展通常在类的实现文件中定义,而不是单独的头文件。扩展允许你隐藏类的一些实现细节,将它们封装在类的实现内部,以防止外部访问或者污染类的接口。

以下是一些关于扩展的要点和使用情况:

  1. 实例变量:你可以使用扩展来向类中添加私有的实例变量(成员变量),这些变量只能在类的内部访问,而外部对象无法直接访问它们。这有助于隐藏对象的内部状态。

  2. 私有方法:你可以在扩展中定义私有方法,这些方法只能在类的实现文件中调用,而不在公共接口中暴露。这可以减少公共接口的复杂性,同时保护实现细节。

  3. 头文件与实现文件:扩展通常在类的实现文件中定义,并使用匿名类别(Anonymous Category)声明。匿名类别是不带类名的类别,它使用 @interface 声明来扩展类的功能。例如:

    // 在实现文件中的扩展
    @interface ClassName ()
    
    // 在此添加私有方法和实例变量
    
    @end
    
  4. 隐藏细节:扩展允许你将一些实现细节隐藏在类的实现中,只暴露给外部需要知道的部分。这有助于提高代码的可维护性和封装性。

  5. 避免冲突:使用扩展可以避免与其他类或类别中的方法名发生冲突。方法和实例变量定义在扩展中通常是私有的,不会与其他类的方法和实例变量发生冲突。

  6. 延伸类的功能:扩展还可以用于添加类的私有扩展,以实现一些特定的功能,而不必将这些功能暴露给整个类的用户。这有助于将类的功能划分为更小的模块。

总之,扩展是 Objective-C 中一种有用的机制,用于封装类的内部细节和提供类的内部实现,同时避免外部对象直接访问或修改这些细节。这有助于提高代码的可维护性和封装性,同时避免潜在的冲突。

8.协议

  1. 协议就类似于c++中定义的一组接口,只声明函数定义,不实现,方法的实现交给类来完成
  2. 可以使用类别来实现非正式协议 (但OC2.0新增了@optional和@required两个关键字后,基本可以完全替代掉非正式协议的功能了)
  3. 使用@protocol关键字来声明
  4. 协议完全支持多继承 正式协议(Formal Protocol)是 Objective-C 中的一种接口定义,它规定了一组方法的声明,但不提供具体的实现。正式协议的定义和使用如下:

定义正式协议

使用 @protocol 关键字来定义正式协议,并在协议内声明方法。协议中可以包括必须实现的方法和可选实现的方法。

@protocol MyProtocol <NSObject>

// 必须实现的方法
- (void)requiredMethod;

@optional
// 可选实现的方法
- (void)optionalMethod;

@end

上述示例中,MyProtocol 是一个正式协议,包含一个必须实现的方法 requiredMethod 和一个可选实现的方法 optionalMethod

遵循协议

类可以选择遵循一个或多个正式协议,以表明它承诺实现协议中声明的方法。遵循协议的类必须提供这些方法的具体实现。

@interface MyClass : NSObject <MyProtocol>
// 类的声明
@end

在上述示例中,MyClass 类遵循了 MyProtocol 协议。

实现方法

遵循协议的类必须在类的实现文件中提供协议中声明的方法的具体实现。

@implementation MyClass

- (void)requiredMethod {
    // 必须实现的方法的具体实现
}

- (void)optionalMethod {
    // 可选实现的方法的具体实现
}

@end

在上述示例中,MyClass 类提供了 requiredMethodoptionalMethod 方法的实现。

多继承协议:记下语法格式

Objective-C 支持一个类遵循多个正式协议,实现多继承的效果。只需在遵循协议的部分使用逗号分隔多个协议名称。

@interface MyClass : NSObject(父类) <MyProtocol1, MyProtocol2, MyProtocol3>(好几个协议)
// 类的声明
@end

在这种情况下,MyClass 类需要提供 MyProtocol1MyProtocol2MyProtocol3 中声明的方法的具体实现。

示例

以下是一个示例,展示了如何定义正式协议、遵循协议、并提供方法实现的完整过程:

// 定义正式协议
@protocol MyProtocol <NSObject>
- (void)requiredMethod;
@optional
- (void)optionalMethod;
@end

// 遵循协议的类
@interface MyClass : NSObject <MyProtocol>
@end

// 实现协议中声明的方法
@implementation MyClass
- (void)requiredMethod {
    NSLog(@"Required method is implemented.");
}
- (void)optionalMethod {
    NSLog(@"Optional method is implemented.");
}
@end

在这个示例中,MyClass 类遵循了 MyProtocol 协议,并提供了协议中声明的方法的具体实现。

正式协议的使用有助于在 Objective-C 中实现接口定义,以确保类提供了特定功能的一致性。协议还可以包括可选方法,这些方法可以由遵循协议的类选择性实现,从而提高了灵活性。正式协议在 iOS 和 macOS 开发中非常常见,用于定义回调、数据源、代理等接口。

多继承父协议的实现

在 Objective-C 中,多继承父协议的实现非常类似于单一继承。你只需要在遵循协议的部分使用逗号分隔多个协议名称,并分别提供这些协议中声明的方法的具体实现。

以下是一个包括多继承父协议、协议定义、实现方法的示例,以及如何使用协议来定义变量的示例:

协议定义

@protocol MyProtocol1 <NSObject>
- (void)methodFromProtocol1;
@end

@protocol MyProtocol2 <NSObject>
- (void)methodFromProtocol2;
@end

类遵循多个协议

@interface MyClass : NSObject <MyProtocol1, MyProtocol2>
@end

实现协议方法

@implementation MyClass
- (void)methodFromProtocol1 {
    NSLog(@"Method from Protocol 1");
}

- (void)methodFromProtocol2 {
    NSLog(@"Method from Protocol 2");
}
@end

使用协议定义变量:记住两种语法格式

你可以使用协议来定义变量,这些变量可以引用遵循了相应协议的对象。这种方式提供了灵活性,因为你可以在不同的对象之间共享相同的接口,而不需要关心它们的具体类别。以下是一个使用协议定义变量的示例:

id<MyProtocol1> object1 = [[MyClass alloc] init];
id<MyProtocol2> object2 = [[MyClass alloc] init];

[object1 methodFromProtocol1]; // 调用 MyProtocol1 中的方法
[object2 methodFromProtocol2]; // 调用 MyProtocol2 中的方法

在这个示例中,object1object2 可以引用 MyClass 对象,因为 MyClass 类遵循了 MyProtocol1MyProtocol2 协议。通过这种方式,你可以在不同的对象之间使用相同的接口,并调用相应协议中定义的方法。

使用协议定义变量的语法格式是 id<ProtocolName>,其中 ProtocolName 是你想要遵循的协议的名称。这种方式在 Objective-C 开发中非常常见,它提供了松耦合的方式来处理对象之间的通信和功能共享。

协议和委托是 Objective-C 编程中非常重要的概念,用于实现对象之间的松耦合通信和功能扩展。它们经常用于代理模式,以实现对象之间的交互和通信。

9. 协议与委托

协议(Protocol)

  1. 定义:协议是一种声明一组方法的机制,但不提供实际的方法实现。它类似于接口(interface)的概念,用于描述类应该具备的某些功能。
  2. 声明:协议由 @protocol 关键字声明,然后在协议中列出一组方法的声明。这些方法通常是抽象的,没有具体的实现。
  3. 实现:类可以选择实现一个或多个协议,这意味着类必须提供协议中声明的方法的具体实现。一个类可以实现多个协议,以扩展其功能。
  4. 多继承:Objective-C 不支持多继承,但你可以通过实现多个协议来实现类似多继承的效果,允许一个类获得多个不同功能的特性。
  5. 使用:协议可以作为对象之间通信的一种契约,一个对象可以将自己的代理指定为遵循了某个协议的另一个对象。协议通常用于定义回调和事件处理。

委托(Delegate)

  1. 定义:委托是一种设计模式,它允许一个对象将某些任务分发给另一个对象来处理。通常,一个对象(委托方)定义一个委托协议,而另一个对象(委托对象)实现这个协议以处理具体的任务。
  2. 工作方式:委托方对象将自己的委托对象设置为一个遵循委托协议的对象。当某些事件或任务发生时,委托方对象将调用委托对象的方法,以便委托对象来处理这些任务。
  3. 使用场景:委托通常用于处理用户界面事件、数据源、通知等,以实现对象之间的交互。委托模式有助于将不同的功能分解为更小的模块,提高代码的可维护性。
  4. 松耦合:委托模式实现了对象之间的松耦合,因为委托方对象不需要知道委托对象的具体类型,只需知道它遵循了特定的协议即可。

在 Objective-C 中,委托通常用于用户界面交互,例如按钮点击事件、表格视图的数据源和委托等。一个常见的示例是 UITableViewDelegateUITableViewDataSource 协议,它们允许视图控制器成为表格视图的委托对象,以处理表格的显示和用户交互。

总之,协议和委托是 Objective-C 中非常有用的编程概念,它们有助于实现对象之间的松耦合通信和功能扩展,提高代码的可维护性和灵活性。这些概念在 iOS 和 macOS 开发中经常用于实现交互和事件处理。

10. 单例模式

单例模式是一种设计模式,它确保一个类只有一个实例,并提供一种全局访问该实例的方式。在 Objective-C 中,单例模式经常用于创建全局共享的对象,如应用程序配置、数据管理、网络请求等。

以下是单例模式的实现方式和示例:

实现方式

在 Objective-C 中,你可以使用以下步骤来实现单例模式:

  1. 创建一个类方法(类方法以 + 开头),该方法用于返回该类的唯一实例。
  2. 在类方法内部,使用静态变量(static variable)来存储唯一的实例,确保它只被创建一次。
  3. 提供一个私有的初始化方法(通常以 init 为前缀),用于实例化对象。这个初始化方法通常会检查实例是否已经存在,如果存在,则返回现有实例;如果不存在,则创建并返回新实例。
  4. 禁用类的默认初始化方法 allocinit,以防止通过这些方法创建多个实例。

示例

下面是一个使用单例模式的示例,创建一个名为 AppSettings 的类,用于管理应用程序的设置信息:

// AppSettings.h
@interface AppSettings : NSObject

@property (nonatomic, strong) NSString *appVersion;
@property (nonatomic, assign) BOOL darkMode;

+ (instancetype)sharedSettings;

@end

// AppSettings.m
@implementation AppSettings

static AppSettings *sharedInstance = nil;

+ (instancetype)sharedSettings {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[self alloc] init];
    });
    return sharedInstance;
}

- (instancetype)init {
    if (self = [super init]) {
        // 初始化设置信息
        _appVersion = @"1.0";
        _darkMode = NO;
    }
    return self;
}

// 禁用默认初始化方法
+ (id)alloc {
    @throw [NSException exceptionWithName:@"Singleton Pattern"
                                   reason:@"Use +sharedSettings for the shared instance"
                                 userInfo:nil];
    return nil;
}

@end

在上述示例中,sharedSettings 方法用 dispatch_once 确保只创建一个实例。初始化方法 init 被用于设置初始属性值。alloc 方法被禁用,以防止通过该方法创建多个实例。

使用单例

现在,你可以在应用程序的任何位置获取 AppSettings 的单例并访问其属性:

AppSettings *settings = [AppSettings sharedSettings];
settings.appVersion = @"2.0";
settings.darkMode = YES;

NSLog(@"App Version: %@", settings.appVersion);
NSLog(@"Dark Mode: %d", settings.darkMode);

单例模式用于维护全局状态或共享资源的情况,确保应用程序中只有一个实例,提供一种方便的方法来访问该实例。这在许多情况下都非常有用,特别是在管理应用程序的全局配置、共享数据、网络请求管理等方面。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值