iOS高手

说一说基类 NSObject(一)

2020-02-20  本文已影响0人  小曼blog

OC是一门动态语言,运行时系统实现了OC的动态性。运行时系统提供了很多方法,但是我们不能直接使用,我们常用的运行时系统的功能定义在了根类NSObject中。也就是说,根类方法中提供了运行时系统的基本功能,根类相当于运行时系统的一个接口

在OC中,只有类方法的概念,没有类变量的概念。

OC中是如何实现“类变量”的呢?
OC中通过实现文件中定义静态变量的方法来代替类变量。

类对象是程序执行过程中自动生成的,每个类只有一个类对象,不需要手动生成。

一、关于isa

NSObject只有一个实例变量,就是Class类型的变量isa,isa用于标识实例对象属于哪个类对象。因为isa决定着实例变量和类的关系,非常重要,所以子类不可以修改isa的值。另外也不能通过直接访问isa来查询实例变量到底属于哪个类,而要通过实例方法class来完成。

二、NSObject的几个常用方法

下面我们就来看看NSObject的常用方法吧。
为了验证这些方法,我们需要一个测试程序。


image.png

ObjectTest.h

//  Copyright © 2020 weiman. All rights reserved.
//

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface ObjectTest : NSObject

@property(nonatomic, copy)NSString * name;

-(id)initWithName:(NSString *)name;

@end

NS_ASSUME_NONNULL_END

ObjectTest.m

//  Copyright © 2020 weiman. All rights reserved.
//

#import "ObjectTest.h"

@implementation ObjectTest

-(id)initWithName:(NSString *)name {
    if (self = [super init]) {
        self.name = name;
    }
    return self;
}

@end

重点来了

我们先打开NSObject.h文件看一看,大致浏览下。
我们看到NSObject.h文件大致有两部分组成,一部分是NSObject协议,一个是NSObject类,NSObject类遵守了NSObject协议,那肯定也会实现该协议中定义的方法,只是我们在声明文件中看不到了。

image.png

点开NSObject类:


image.png

在main文件中的main方法中进行测试。
先定义两个对象,一个是NSObject类型的,一个是ObjectTest类型的。

 NSObject * obj = [[NSObject alloc] init];
 ObjectTest * test = [[ObjectTest alloc] initWithName:@"小米粒"];

1.对象方法class
-(Class)class OBJC_SWIFT_UNAVAILABLE("use 'type(of: anObject)' instead");
说明:
OBJC_SWIFT_UNAVAILABLE("use 'type(of: anObject)' instead");的意思是在swift中使用type(of: anObject)来代替class 方法。这是题外话,不用在意。
对象方法class定义在protocol NSObject中,NSObject类遵守了
这个协议,也就在NSObject的实现文件中实现了这个方法。

对象方法class返回对象所属的类的类对象。

测试代码:

        NSLog(@"-------------对象方法class-----------------");
        NSLog(@"obj class, %@",[obj class]);
        NSLog(@"test class, %@",[test class]);
        printf("\n");

打印结果:


image.png

2.类方法class
+(Class)class OBJC_SWIFT_UNAVAILABLE("use 'aClass.self' instead");
类方法class,定义在NSObject类中,是NSObject类的一个公有方 法,返回类对象。

测试程序:

        NSLog(@"-------------类方法class-----------------");
        NSLog(@"NSObject class, %@", [NSObject class]);
        NSLog(@"ObjectTest class, %@", [ObjectTest class]);
        printf("\n");

打印结果:


image.png

3.对象方法self,也是定义在NSObject协议中的,声明为:
- (instancetype)self;
此方法返回对象自身,是一个无任何实际动作,但是很有用的方法。

测试程序:

        NSLog(@"-------------对象方法self-----------------");
        NSLog(@"obj self, %@",[obj self]);
        NSLog(@"test self, %@",[test self]);
        NSLog(@"test self, %@",[test self].name);
        printf("\n");

打印结果:


image.png

4.对象方法isMemberOfClass也是定义在协议中的一个方法,声明为:
- (BOOL)isMemberOfClass:(Class)aClass;
用于判断对象是不是参数aClass类的对象。

注意:这个方法判断的时候,如果参数是父类,则返回NO。

测试程序:

        BOOL isTest = [test isMemberOfClass:[NSObject class]];
        BOOL isTest2 = [test isMemberOfClass:[ObjectTest class]];
        BOOL isTest3 = [obj isMemberOfClass:[ObjectTest class]];
        BOOL isTest4 = [obj isMemberOfClass:[NSObject class]];
        NSLog(@"-------------isMemberOfClass--------------");
        NSLog(@"test 是不是 NSObject 类型?%@", isTest ? @"是" : @"否");
        NSLog(@"test 是不是 ObjectTest 类型?%@", isTest2 ? @"是" : @"否");
        NSLog(@"obj 是不是 ObjectTest 类型?%@", isTest3 ? @"是" : @"否");
        NSLog(@"obj 是不是 NSObject 类型?%@", isTest4 ? @"是" : @"否");
        printf("\n");

打印结果:


image.png

5.对象方法isKindOfClass也是定义在协议中的,声明为:
- (BOOL)isKindOfClass:(Class)aClass;
作用于isMemberOfClass类似,但是也有不同。这个方法的作用是判断消息接受者是否是参数aClass类或者aClass的父类的实例。

测试程序:

        BOOL isTestKind = [test isKindOfClass:[NSObject class]];
        BOOL isTestKind2 = [test isKindOfClass:[ObjectTest class]];
        BOOL isTestKind3 = [obj isKindOfClass:[ObjectTest class]];
        BOOL isTestKind4 = [obj isKindOfClass:[NSObject class]];
        NSLog(@"-------------isKindOfClass--------------");
        NSLog(@"test 是不是 NSObject 类型?%@", isTestKind ? @"是" : @"否");
        NSLog(@"test 是不是 ObjectTest 类型?%@", isTestKind2 ? @"是" : @"否");
        NSLog(@"obj 是不是 ObjectTest 类型?%@", isTestKind3 ? @"是" : @"否");
        NSLog(@"obj 是不是 NSObject 类型?%@", isTestKind4 ? @"是" : @"否");
        printf("\n");

打印结果:


image.png

6.类方法isSubclassOfClass定义在NSObject类的一个公有方法, 声明为:
+(BOOL)isSubclassOfClass:(Class)aClass;
判断消息接收者是不是参数aClass的子类或者自身。

测试程序:

        BOOL isTestsub = [NSObject isSubclassOfClass:[test class]];
        BOOL isTestsub2 = [ObjectTest isSubclassOfClass:[test class]];
        BOOL isTestsub3 = [NSObject isSubclassOfClass:[obj class]];
        BOOL isTestsub4 = [ObjectTest isSubclassOfClass:[obj class]];
        BOOL isTestsub5 = [ObjectTest isSubclassOfClass:[NSObject class]];
        NSLog(@"-------------isSubclassOfClass-----------");
        NSLog(@"NSObject 是不是 test所属类 的子类或自身?%@", isTestsub ? @"是" : @"否");
        NSLog(@"ObjectTest 是不是 test所属类 的子类或自身?%@", isTestsub2 ? @"是" : @"否");
        NSLog(@"NSObject 是不是 obj所属类 子类或自身?%@", isTestsub3 ? @"是" : @"否");
        NSLog(@"ObjectTest 是不是 obj所属类 子类或自身?%@", isTestsub4 ? @"是" : @"否");
        NSLog(@"ObjectTest 是不是 NSObject 子类或自身?%@", isTestsub5 ? @"是" : @"否");
        printf("\n");

打印结果:


image.png
  1. superclass,定义在协议中,是一个只读的属性。
    @property (readonly) Class superclass;
    我们可以使用对象来调用superclass,就像一个对象方法一样,其实是调用它的getter方法。
    superclass的作用是:返回对象所在类的父类。

为了更好的说明,我们再建一个新的类TestSon,继承自ObjectTest。


image.png

TestSon.h

#import "ObjectTest.h"

NS_ASSUME_NONNULL_BEGIN

@interface TestSon : ObjectTest

-(void)sayHi;

@end

TestSon.m

#import "TestSon.h"

@implementation TestSon

-(void)sayHi {
    NSLog(@"Hi, I am son class");
}

@end

测试程序:

        NSLog(@"-------------对象方法superclass-----------");
        
        TestSon * son = [[TestSon alloc] initWithName:@"小苗苗🌹"];
        
        NSLog(@"obj superclass:%@",[obj superclass]);
        NSLog(@"test superclass:%@",[test superclass]);
        NSLog(@"son superclass:%@",[son superclass]);
        NSLog(@"son superclass:%@",son.superclass);
        NSLog(@"son name%@",[son name]);
        NSLog(@"son name%@",son.name);
        printf("\n");

打印结果:


image.png
  1. 类方法superclass,定义在NSObject类中,返回类对象。
    + (Class)superclass;

测试程序:

        NSLog(@"NSObject superclass:%@",[NSObject superclass]);
        NSLog(@"ObjectTest superclass:%@",[ObjectTest superclass]);
        NSLog(@"TestSon superclass:%@",[TestSon superclass]);
        NSLog(@"NSString superclass:%@",[NSString superclass]);
        NSLog(@"NSArray superclass:%@",[NSArray superclass]);
        NSLog(@"NSMutableArray superclass:%@",[NSMutableArray superclass]);

打印结果:


image.png

本节内容回顾:

一、类对象的概念

OC中把类也作为一种对象看待,每个类有且只有一个类对象,程序运行过程中自动生成。

二、Class类型说明

所有类对象的类型是Class。

三、NSObject的几个常用方法

当然了,NSObject的常用方法还有很多,后面再一一学习,本节我们就学习了8个,分别是:

  1. -(Class)class;
    返回对象的类对象。
    2.+(Class)class;
    返回类的类对象。
    3.-(id)self;
    返回对象自身实例。
    4.-(BOOL)isMemberOfClass:(Class)aClass;
    判断是否是参数类对象aClass的实例。不包含父类。
    5.-(BOOL)isKindOfClass:(Class)aClass;
    判断是否是参数类对象aClass的实例。包含父类。
    6.-(BOOL)isSubclassOfClass:(Class)aClass;
    判断是否是参数类对象aClass的子类或者自身。
    7.-(Class)superclass;
    返回实例对象所在类的父类。
    8.+(Class)superclass;
    返回类对象的父类。

祝大家生活愉快!

上一篇下一篇

猜你喜欢

热点阅读