ObjectiveC-10-OOP面向对象程序设计-分类/类别

news2025/2/27 4:33:24

类别(Category)是OjectiveC的一个特性,主要目的是让开发者可以以模块的形式向类添加方法(扩展),创建标准化的方法列表供给其他人实现。

有些文档也会翻译成类别,其实是一个意思。

概述

语法说明

类别提供了一个简单的方式,将类定义模块化到相关组或分类中,同时也提供了扩展现有类定义的简便方式。换句话说,它的功能有些类似于接口继承,但又比继承简单和强大,在使用时需要结合继承一起使用,其能力是非常厉害的。 分类的语法如下:

@interface Fraction(Category1) //类名+(类别名称)
 //分类方法的代码
@end
@interface Fraction(Category2)
 //分类方法的代码
@end

类别的作用

如果在xcode中使用新建文件功能创建Cocoa class文件,会自动生成.h和.m文件。在这种分离的设计基础上附加分类后,可以使用分类实现下面三个方面的能力增强:

  1. 扩展现有类库的功能:比如扩展NSString、NSObject类,这种方式某些书中扩展NSObject类有时被称为非正式协议;
  2. 扩展现有类的声明:定义一个声明,然后分模块实现,比如在一个.h文件中定义类声明,然后分多个.m实现,一个.m实现其中一个分类,这样方便分工合作;
  3. 为现在的自定义类添加私有方法而不必重新定义子类;

类别规则

  1. 类别文件名称一般是是“类名称+类别名称”来命名,这是一个不成文的规定;
  2. 类别中可以添加属性,但不能添加实例变量,而且属性必须是@dynamic类型的;
  3. 如果类别方法与现有类的方法重名,类的方法会被覆盖掉,一旦覆写后外部就不能访问原来的方法了,所以这块要特殊设计一下;
  4. 如果多个分类中有同名的方法,可能会引起混乱;分类后不仅会影响当前类,也会影响所有的子类;
  5. 类别的名称是在类的范围内是唯一的;

创建类别

在新建文件中,选择Objective-C文件类型
在这里插入图片描述
在配置界面做如下配置,注意File Type选择 Category:
在这里插入图片描述
最后生成如下项目工程文件如下:
在这里插入图片描述

类别能力

给现有类添加新方法

类别可以为所有类添加新方法,包括系统类库和自定义的类。下面的代码就用一个自定义的类别来扩展系统提供的NSString类库的功能。

  • 类别定义
//扩展系统NSString,添加一个名为NumberConvenience的类别
#import <Foundation/Foundation.h>

@interface NSString (NumberConvenience)

- (NSNumber *)lengthAsNumber; //添加一个新方法

@end

  • 类别实现
#import "NSString+NumberConvenience.h"

@implementation NSString (NumberConvenience)

- (NSNumber *)lengthAsNumber{
    NSUInteger length = [self length];
    return ([NSNumber numberWithUnsignedInt:length]);
} // lengthAsNumber

@end
  • 类别测试
#import <Foundation/Foundation.h>
#import "NSString+NumberConvenience.h"

int main(int argc, const char * argv[]){
    @autoreleasepool
    {
        NSMutableDictionary *dict = [NSMutableDictionary dictionary];
        [dict setObject:[@"hello" lengthAsNumber] forKey:@"hello"];
        NSLog (@"%@", dict);
    }
    return 0;
}

类能力(声明)的动态扩展

有别于上面的给现有类添加新方法的实现,类功能的动态扩展不需要新建文件,也可以实现定义实例变量。

方法是创建一个未命名的分类,然后在()中不指定任何名字,在这个类中可以扩展实例变量和属性(在有命名的分类中是不允许的)。未命名分类中的方法需要在主实现区中实现,而不是在分离的实现区中实现。

在未命名类别中的扩展的属性必须是私有的

  • 自定义类,Fraction是一个自定义的类,用于此示例的测试
#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

//原始接口声明
@interface Fraction : NSObject

@property (assign) NSInteger thing1;
//标记为只读属性
@property (readonly, assign) NSInteger thing2;

- (void)resetAllValues;

@end
  • 扩展自定义类的属性和方法
@interface Fraction() //空
NS_ASSUME_NONNULL_END
{
    NSInteger thing4; //添加了新实例变量
}
@property (readwrite, assign) NSInteger thing2; //覆盖了原有属性
@property (assign) NSInteger thing3; //添加了新私有属性
@end
  • 实现自定义类
#import "Fraction.h"

@implementation Fraction

- (void)resetAllValues
{
    self.thing1 = 200;
    self.thing2 = 300;
    self.thing3 = 400;
    thing4 = 5;
}

- (NSString *) description
{
    NSString *desc = [NSString stringWithFormat: @"%d %d %d %d", _thing1, _thing2, _thing3, thing4];
    
    return (desc);
    
} // description

@end
  • 测试代码
#import <Foundation/Foundation.h>
#import "NSString+NumberConvenience.h"
#import "Fraction.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        
        NSMutableDictionary *dict = [NSMutableDictionary dictionary];
        
        [dict setObject:[@"hello" lengthAsNumber] forKey:@"hello"];
        
        NSLog (@"%@", dict);
        
        
        Fraction *things = [[Fraction alloc] init];
        things.thing1 = 1;
        NSLog(@"%@", things); //~1 0 0 0
         
        //重新赋值
        [things resetAllValues];
        NSLog(@"%@", things); //~200 300 400 5
    }
    return 0;
}

类分文件实现

前面所有的代码实现全是一个.h,一个m。如果是大型项目的话.m中的代码量可能非常区大,这里可以采用两种不同的设计方案解决:拆类或是分类。除了代码整洁外,还可以多人协作以及实现代码分包存储等功能,打破了继承这种约束。
在这里插入图片描述

即定义一个.h,多个.m实现这样的模式来分散类的实现,每个.m实现一个类别接口,示例代码如下:

类别定义

在这里插入图片描述

//类别定义
#import <Foundation/Foundation.h>

@interface CategoryThing : NSObject
{
  NSInteger thing1;
  NSInteger thing2;
  NSInteger thing3;
}
@end // CategoryThing

// Category thing1
@interface CategoryThing (Thing1)
- (void)setThing1:(NSInteger)thing1;
- (NSInteger)thing1;
@end

// Category thing2
@interface CategoryThing(Thing2)
- (void)setThing2:(NSInteger)thing2;
- (NSInteger)thing2;
@end // CategoryThing (Thing2)

// Category thing3
@interface CategoryThing (Thing3)
- (void)setThing3:(NSInteger)thing3;
- (NSInteger)thing3;
@end // CategoryThing (Thing3)

类别实现

在这里插入图片描述

#import "CategoryThing.h"

@implementation CategoryThing (Thing1)
- (void)setThing1:(NSInteger)t1{
    thing1 = t1;
}

- (NSInteger) thing1{
    return (thing1);
}

@end // CategoryThing
#import "CategoryThing.h"

@implementation CategoryThing (Thing2)

- (void)setThing2:(NSInteger) t2{
    thing2 = t2;
}

- (NSInteger)thing2{
    return (thing2);
}

@end 
\#import "CategoryThing.h"

@implementation CategoryThing (Thing3)

- (void)setThing3:(NSInteger) t3{
    thing3 = t3;
}

- (NSInteger)thing3{
    return (thing3);
}

@end 

程序测试

main测试

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

int main(int argc, const char * argv[])
{
    @autoreleasepool
    {
        CategoryThing *thing = [[CategoryThing alloc] init];
        
        [thing setThing1: 5];
        [thing setThing2: 23];
        [thing setThing3: 42];
        
        NSLog (@"Things are %@", thing); //Things are 5 23 42
    }
    return 0;
}

end…

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1571696.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

个人品牌打造IP孵化运营培训教程架构课件

【资料持续更新&#xff0c;以防走丢】 个人品牌打造IP孵化运营培训教程架构课件 部分资料预览 资料部分是网络整理&#xff0c;仅供学习参考。 个人品牌运营合集 &#xff08;完整资料包含以下内容&#xff09;目录 详细的个人IP运营方案&#xff1a; 1. 确定个人定位和…

0基础学习Mybatis系列数据库操作框架——自定义类型处理器

大纲 Java模型类定义类型处理器配置文件和类型绑定和字段绑定resultMap中绑定 Mapper代码测试类型对应关系表总结参考资料 我们有时候会在数据库中放入一个扩展字段&#xff0c;用于保存在表设计时尚未考虑到的、未来会加入的一些信息。这个字段我们一般使用字符串存储&#xf…

数学矩阵GCD和lCM(详解)

矩阵乘法 知阵乘法是《线性代数》中的基础内容&#xff0c;但在考察数学的算法题中也会出现。 本节我们学习基础的矩阵乘法规则。 每个矩阵会有一个行数和一个列数&#xff0c;只有当相乘的两个矩阵的左矩阵的列数等于右矩阵的行数 时&#xff0c;才能相乘&#xff0c;否则不允…

JavaSE-10笔记【多线程1(+2024新)】

文章目录 1.进程与线程2.并发与并行3.线程的调度模型4.实现线程4.1 第一种方式&#xff1a;继承Thread4.2 第二种方式&#xff1a;实现Runnable接口4.3 t.start()和t.run()的本质区别&#xff1f;4.4 线程常用的三个方法 5.线程的生命周期&#xff08;把生命周期图背会&#xf…

考研回忆录【二本->211】

备考时长差不多快一年半&#xff0c;从22年的11月底开始陆陆续续地准备考研&#xff0c;因为开始的早所以整个备考过程显得压力不是很大&#xff0c;中途还去一些地方旅游&#xff0c;我不喜欢把自己绷得太紧。虽然考的不是很好&#xff0c;考完我甚至都没准备复试&#xff0c;…

《QT实用小工具·十三》FlatUI辅助类之各种炫酷的控件集合

1、概述 源码放在文章末尾 FlatUI辅助类之各种炫酷的控件集合 按钮样式设置。文本框样式设置。进度条样式。滑块条样式。单选框样式。滚动条样式。可自由设置对象的高度宽度大小等。自带默认参数值。 下面是demo演示&#xff1a; 项目部分代码如下所示&#xff1a; #ifnd…

《QT实用小工具·十四》面板容器控件和图形字体示例

1、概述 源码放在文章末尾 面板容器控件包含如下功能&#xff1a; 支持所有widget子类对象&#xff0c;自动产生滚动条。 支持自动拉伸自动填充。 提供接口获取容器内的所有对象的指针。 可设置是否自动拉伸宽度高度。 可设置设备面板之间的间距和边距。 超级图形字体类…

论文笔记:Large Language Models as Analogical Reasoners

iclr 2024 reviewer打分5558 1 intro 基于CoT prompt的大模型能够更好地解决复杂推理问题 然而传统CoT需要提供相关的例子作为指导&#xff0c;这就增加了人工标注的成本——>Zero-shot CoT避免了人工标注来引导推理 但是对于一些复杂的任务难以完成推理&#xff0c;例如c…

2024最全AI绘画Midjourney绘画提示词Prompt大全,AI换脸、垫图混图【宝藏级收藏】

一、AI绘画工具 SparkAi创作系统是基于ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;那么如何搭建部署AI创作ChatGPT&#xff1f;小编这里写一个详细图文教程吧。已支…

Win10 下 git error unable to create file Invalid argument 踩坑实录

原始解决方案参看&#xff1a;https://stackoverflow.com/questions/26097568/git-pull-error-unable-to-create-file-invalid-argument 本问题解决于 2024-02-18&#xff0c;使用 git 版本 2.28.0.windows.1 解决方案 看 Git 抛出的出错的具体信息&#xff0c;比如如下都来自…

7(8)-2-CSS 盒子模型

个人主页&#xff1a;学习前端的小z 个人专栏&#xff1a;HTML5和CSS3悦读 本专栏旨在分享记录每日学习的前端知识和学习笔记的归纳总结&#xff0c;欢迎大家在评论区交流讨论&#xff01; 文章目录 CSS 盒子模型1 盒子模型&#xff08;Box Model&#xff09;组成2 边框&#x…

Git 如何去使用

目录 1. Git暂存区的使用 1.1. 暂存区的作用 1.2. 暂存区覆盖工作区&#xff08;注意&#xff1a;完全确认覆盖时使用&#xff09; 1.3. 暂存区移除文件 1.4. 练习 2. Git回退版本 2.1. 概念 2.2. 查看提交历史 2.3. 回退命令 2.4. 注意 3. Git删除文件 3.1. 需求 …

docker安装Nexus,maven私服

文章目录 前言安装创建文件夹设置文件夹权限docker创建指令制作docker-compose.yaml文件 查看网站访问网页查看密码 前言 nexus作为私服的maven仓库&#xff0c;在企业级应用中&#xff0c;提供了依赖来源的稳定性&#xff0c;为构建庞大的微服务体系&#xff0c;打下基础 安…

Day83:服务攻防-开发组件安全JacksonFastJson各版本XStreamCVE环境复现

目录 J2EE-组件Jackson-本地demo&CVE 代码执行 (CVE-2020-8840) 代码执行 (CVE-2020-35728&#xff09; J2EE-组件FastJson-本地demo&CVE FastJson < 1.2.24 FastJson < 1.2.47 FastJson < 1.2.80 (利用条件比较苛刻) J2EE-组件XStream-靶场&CVE …

Java_自定义实体类的列表List<T>调用remove()失败讲解

示例1 前提&#xff1a; 新建一个主类Demo1。 需求&#xff1a; 在一个列表中有三条String的数据&#xff0c;想要使用remove(Object o)删掉其中一条。 结果&#xff1a; remove(Object o)成功把数据删掉。 示例2 前提&#xff1a; 新建一个自定义实体类DataExample和一个主…

PC发送指令给单片机控制LED(与上一篇文章相反)

此时要重新配置寄存器 &#xff0c;实现电脑往单片机传输数据 1、配置SCON寄存器的REN 即 REN 1 2、有TI&#xff08;发送中断&#xff09;就有RI&#xff08;接收中断&#xff09; 3、优化 发现发送 o 时&#xff0c;D5亮灯会有延迟 下面就是做到真正的无延迟的全双工通信 …

STC89C51学习笔记(四)

STC89C51学习笔记&#xff08;四&#xff09; 综述&#xff1a;本文讲述了在STC89C51中数码管、模块化编程、LCD1602的使用。 一、数码管 1.数码管显示原理 位选&#xff1a;对74HC138芯片的输入端的配置&#xff08;P22、P23、P24&#xff09;&#xff0c;来选择实现位选&…

Android 代码自定义drawble文件实现View圆角背景

简介 相信大多数Android开发都会遇到一个场景&#xff0c;给TextView或Button添加背景颜色&#xff0c;修改圆角&#xff0c;描边等需求。一看到这样的实现效果&#xff0c;自然就是创建drawble文件&#xff0c;设置相关属性shap&#xff0c;color&#xff0c;radius等。然后将…

第二节课《轻松玩转书生·浦语大模型趣味 Demo》

比较匆忙&#xff0c;假期前仿照第一期课程的内容好像被清空了&#xff0c;重新搭建一次。 https://github.com/InternLM/Tutorial/blob/camp2/helloworld/hello_world.md 按照那老师写好的&#xff0c;一步步复制就好了 浦语灵笔2的大概率是会超出显存&#xff0c;先不测试了…

JavaScript权威指南(第7版) 笔记 - 扩展操作符总结

扩展操作符 ... &#xff0c;不是真正意义上的JavaScript操作符。 let str "0123ABC" console.log(typeof ...str);// Uncaught SyntaxError: Unexpected token ... 上面的第2行代码会报错&#xff0c;… 操作符只能在数组字面量、对象字面量、函数调用中使用。 在…