[Objective-C]哲学大师-通过共性与个性的概念来理解类与对象

本文介绍了哲学中的共性与个性概念,并以此来解释面向对象编程中的类和对象。类代表共性,包含成员变量和方法,而对象是类的实例,具有个性。文章详细阐述了如何在Objective-C中定义类(接口和实现部分)、创建对象、调用方法以及使用self关键字。此外,还讨论了可变参数的方法和单例模式的应用,以及isKindOfClass和isMemberOfClass类方法的使用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

哲学大师-通过共性与个性的概念来理解类与对象

如何理解

什么是共性与个性

相信看过高中必修三的大家都有印象,但是我们还是来复习一下吧

共性指不同事物的普遍性质;个性指一事物区别于其他事物的特殊性质
共性和个性是一切事物固有的本性,每一事物既有共性又有个性
共性决定事物的基本性质;个性揭示事物之间的差异性

怎么把理解类与对象

类即类别,可以看成是共性
对象也称实例,可以看成是个性

对标上述三点:

  1. 类具有不同对象的普遍性质;对象内的数据又有区别其他对象的特殊性质
  2. 每个对象都有属于的类,每个对象都有它自己的数据,又有类的成员变量与方法
  3. 类决定它的对象的变量与方法,不同对象之间存储的数据可以不同

类与对象里面有什么

对于面向编程来说,有两个非常重要的概念:成员变量方法

  1. 成员变量:用于描述该类的对象状态的数据

  2. 方法:用于描述该类的行为

如何定义

怎么去定义一个类

Objective-C 中定义类有两个步骤 定义接口部分与实现部分

  1. 接口部分:定义该类包含的成员变量与方法
  2. 实现部分:为该类的方法提供实现

定义类的接口部分

  1. 用 @interfac 来声明类的接口部分
  2. 用紧跟类的一对花括号声明该类成员变量
  3. 后面部分声明该类的方法
  4. 用 @end 表示声明结束

如下

//ECPerson.h
#import<Foundation/Foundation.h>

@interface ECPerson : NSObject
//interface 中文意思即接口
//Myclass 是此处定义的类名
// NSObject 是 Myclass 继承的父类名
{
	int _age;
	NSString* _name;
	//可以使用任何类型
	//变量名应为下划线 + 驼峰命名法
}

- (void)setName: (NSString*)name andAge: (int)age;
//‘-’ 表示该方法为实例方法;对象又称实例
//在方法声明中,所有的类型都应该用圆括号括起
//id 可以代表所有对象类型,会在运行时候确定需要动态调用的方法而非在编译时候确定(动态绑定)
- (void)say: (NSSting*)content;
- (NSString*) info;
+ (void)foo;
//‘+’ 表示该方法为类方法
//二者不可混淆 对象方法调用者只能是对象,类方法同理
@end

Object-C 的方法签名:
“方法名” + “:” + ”形参声明“
无冒号即该方法不带形参声明

定义类的实现部分

  1. 类实现部分的类名应该与接口部分相同
  2. 实现部分也可在声明成员变量,但是只能在实现部分使用
  3. 必须为接口部分每个方法提供方法定义

看看语法

//ECPerson.m
#import"ECPerson.h"

@implementation ECPreson {
	int _testAttr;
	//只能用于实现部分,相当于被隐藏
}
- (void)setName: (NSString*)n andAge: (int) a {
	_name = n;
	//方法形参名不同是被允许的
	//相同反而更麻烦,重名时局部变量会覆盖成员变量
	_age = a;
}
- (void)say: (NSString*)content {
	NSLog(@"%@", content);
}
- (NSString*) info {
	[self test];
	return [NSString stringWithFomat: @"name %@, age %d.", _name, _age];
}
- (void)test {
	NSLog(@"1");
	//只能在实现部分使用的方法
}
+ (void) foo {
	NSLog(@"ECPerson");
	//可通过类名调用
}

如何使用

如何去定义一个变量

语法格式如下
类名 变量名;*

如何去创建一个对象

语法格式如下
[[类名 alloc] 初始化方法];

alloc 是 Objective-C 的关键字,负责为该类分配空间,创建对象 分配空间之后是初始化,由于所有对象都继承 NSObject
类,故都有一个默认初始化方法 init 也支持 用 new 初始化,但是不建议,所以不过多介绍了

如何去调用类方法

无论调用类方法还是实例方法,结构都是一样的,需要有主谓宾三个部分

语法格式如下
[调用者 方法名:参数 形参标签:参数值 …];

如果声明多个形参,需要为每个形参传入相应的值
实例方法必须用实例调用,类方法必须用类调用

Objective-C 允许直接通过对象访问成员变量

语法格式如下
对象->变量名;

除此之外

如何运用 self 关键字

self 表示出现方法(只应在方法中出现)中的调用者,可以通过其访问该类的另一个方法或成员变量,也可做返回值
具体怎么样做呢?来看看吧

#import<Foundation/Foundation.h>
#import"ECDog.h"

@implementation ECDog 
- (void)jump {
	NSLog(@"doing jump");
}
- (void)run {
	[self jump];
	NSLog(@"doing  run");
}
@end

self 总是代表当前方法的调用者,谁在调用该方法,self 就代表谁
通过 self 也可以避免成员变量被局部变量覆盖,实现强行访问成员变量

形参个数可变的方法

在最后一个形参名后加逗号与三个点
注意: 个数可变的形参只能处于列表的最后,即一个方法中最多只能有一个个数可变的形参
光说不练怎么行,来看我定义一个方法

#import<Foundation/Foundation.h>

@interface VarArgs: NSObject 
- (void)test: (NSString*)name, ...;
@end

那么如何获取呢?
可以通过以下关键字

  1. va_list 用于定义指向列表的指针变量的类型
  2. va_start 指定开始处理的列表并让指针变量指向第一个参数的函数
  3. va_end 结束处理可变形参,释放指针变量的函数
  4. va_arg 返回获取指针当前指向参数的值,并将指针移动到下一个参数的函数

不难看出,上述关键词操作类似于链表操作,故也可以把其看作链表而非列表来理解

来看看实现吧

#import"VarArgs.h"

@implementation VarArgs
//arg 即自变量 argument 的缩写
- (void)test: (NSString*)name, ... {
	va_list argList;
	//类似初始化链表
	if (name) {
		//先确定 name 是存在的
		NSLog(@"%@", name);
		va_start(argList, name);
		//类似获取链表头指针
		NSString* arg = va_arg(argList, id);
		//类似逐个遍历链表
		while (arg) {
			NSLog(@"%@",arg);
			arg = va_arg(arglist, id);
		}
		va_end(argList);
		//类似释放链表
	}
}
@end
int main(int argc, char* argv[]) {
	@autoreleasepool {
		VarArgs* va = [[VarArgs alloc] init];
		[va test: @"111", @"222", @"333", nil];
		//最后一个为 nil 以明确结束点
	}
}

本篇小结

  1. 类与对象可以理解为共性与个性的关系
  2. 类与对象中包含成员变量与方法两个重要概念
  3. 定义类需要定义其接口与实现两个部分
  4. 定义一个变量与创建一个对象的语法格式
  5. 调用类与实例方法与直接访问成员变量
  6. 通过self关键字调用方法的调用者
  7. 形参个数可变但是最多只有有一个在最后

另1 单例

如果一个类始终只能创建一个实例,则这个类被称为单例类

单例类可通过 static 全局变量 来实现
每次程序需要获取该实例时,都要先判断该全局变量是否为 nil
如果该全局变量为nil,则初始化一个实例并赋值给全局变量
如果该全局变量不为nil,那么程序直接返回该全局变量指向的实例

#import <Foundation/Foundation.h>
@interface FKSingleton: NSObject 
+ (id)instance;
@end

在上面程序中的 instance 类方法 ,允许程序通过该 类方法来获取该类的唯一实例
在实现部分将会定义一个全局变量,并缓存己有的实例,然后实现 instance 类方法
在该类方法中控制FKSingleton 类最多只会产生一个实例

#import "FkSingleton.h"
@implementation FKSingleton 
static id instance= nil;
+ (id) instance {
	//如果instanc e全局变量为nil 
	if (!instance) {
		//创建一个Singleton 实例,并将该实例赋给instance 全局变量 
		instance = [[super alloc] init];
		return instance;
	}
}
@end

int main (int arge , char* argv [])
@autoreleasepool {
	// 判断两次获取的实例是否相等
	NSLog (@"%d"[FKSingleton instance] == [FKSingleton instance]);
)

上面程序中粗体字代码用于控制通过instance 类方法来获取FKSingleton 实例时,程序最
多只会产生一个Singleton 实例

另2 is MemberOfClass 的类方法理解

当调用者是——元类MetaClass 时

+(BOOL)isKindOfClass:(Class)cls :

判断cls是不是 根元类->NSObject 中的任意一个

+(BOOL)isMemeberOfClass:(Class)cls :

判断cls是不是根元类

如下代码的运行结果,可验证上文

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        //instacne-isKindOfClass
               BOOL res1 = [[NSObject class] isKindOfClass:[NSObject class]];
               BOOL res3 = [[Person class] isKindOfClass:[Person class]];
               BOOL res10 = [[NSString class] isKindOfClass:[NSObject class]];

               NSLog(@"%d %d %d",res1, res3, res10);
               
               
               Person *person = [[Person alloc] init];
       //        BOOL res5 = [[Person class] isKindOfClass:[NSObject class]];
       //        BOOL res6 = [person isKindOfClass:[NSObject class]];
       //        NSLog(@"%d %d", res5, res6);
       //
               //instance-isMemberOfClass
//               BOOL res2 = [[NSObject class] isMemberOfClass:[NSObject class]];
//               BOOL res7 = [person isMemberOfClass:[NSObject class]];
//               BOOL res8 = [[Person class] isMemberOfClass:[NSObject class]];
//               BOOL res9 = [person isMemberOfClass:[Person class]];
//               NSLog(@"%d %d %d %d" ,res2, res7, res8, res9);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值