技术标签: objective-c iOS笔记
类似于接口,用于定义多个类应该遵守的规范,但不会为这些方法提供实现,方法的实现则交给类去完成。
由图可看出,同一个类的内部状态数据、各种方法的实现细节完全相同,类是一种具体实现体。而协议则定义了了一种规范,协议定义某一批类所需要遵守的规范,它不关心这些类的内部状态数据,也不关心这些类里方法的实现细节,它只规定这批类中必须提供某些方法,提供这些方法的类就可满足实际需要。
协议不提供任何实现。协议体现的是规范和实现分离的设计哲学。让规范和实现分离也正是协议的好处,是一种松耦合的设计。
类别(catgory)可以实现非正式协议,这种类别以NSObject为基础,为NSObject创建类别,创建类别时即可指定该类别应该新增的方法。
当某个类实现NSObject的该类别时,就需要实现该类别下的所有方法,这种基于NSObject定义的类别即可认为是非正式协议。
例如:
#import <Foundation/Foundation.h>
//以NSObject为基础定义Eatable类别
@interface NSObject (Eatable)
- (void) taste;
@end
上面为NSObject的Eatable类别中定义了一个taste:方法,接下来所有继承NSObject类的子类都会自动带有该方法,而且NSObject的子类可以根据需要,自行决定是否要实现该方法。
Eatable类别作为一个非正式协议使用,那么相当于定义了一个规范,因此,遵守该协议的子类通常都会实现这个方法。
#import <Foundation/Foundation.h>
#import "NSObject+Eatable.h"
//定义类的接口部分
@interface FKApple : NSObject
@end
#import "FKApple.h"
//为FKApple提供实现部分
@implementation FKApple
- (void) taste {
NSLog(@"苹果营养丰富,口味很好!");
}
@end
从上述的程序可以看到,虽然接口部分没有定义任何方法,但是这丝毫不会影响到该类的功能,因为它继承了NSObject(Eatable),只要在FKApple类的实现部分实现taste方法即可。
#import <Foundation/Foundation.h>
#import "FKApple.h"
int main(int argc, char* argv[]) {
@autoreleasepool {
FKApple* app = [[FKApple alloc] init];
[app taste];
}
return 0;
}
输出结果为:
Objective-C并不强制实现该协议中的所有方法,但是若不实现FKApple类中的taste方法,而且非正式协议本身也没有实现该方法,就会引发下面的错误:
@protocol 协议名 <父协议1, 父协议2>
{
零个到多个方法定义...
}
上面语法的详细说明如下:
协议定义的是多个类共同的公共行为规范,因此,协议里所有的方法都是公开访问权限。
#import <Foundation/Foundation.h>
//定义协议
@protocol Output
//定义协议的方法
- (void) output;
- (void) addData: (NSString*) msg;
@end
上面定义了一个Output协议,其中定义了两个方法,而协议并不关心方法的实现,就相当于定义了一个接口。
#import <Foundation/Foundation.h>
//定义协议
@protocol Productable
//定义协议的方法
- (NSDate*) getProduceTime;
@end
#import <Foundation/Foundation.h>
#import "Output.h"
#import "Productable.h"
//定义协议,继承了上面两个协议
@protocol Printable <Output, Productable>
//定义协议的方法
- (NSString*) PrintColor;
@end
协议的继承和类继承不一样,协议完全支持多继承,即一个协议可以有多个直接的父协议。和类继承相似,子协议继承某个父协议,将会获得父协议里定义的所有方法。
一个协议继承多个父协议时,多个父协议排在<>中间,多个协议口之间以英文逗号( , )隔开。
@interface 类名: 父类 <协议1, 协议2...>
从上面的语法格式可以看出,一个类可以同时遵守多个协议。
#import <Foundation/Foundation.h>
#import "Printable.h"
//定义类的接口部分,继承NSObject,遵守Printable协议
@interface Printer : NSObject <Printable>
@end
#import "Printer.h"
#import "Printable.h"
#define MAX_CACHE_LINE 10
@implementation Printer
{
NSString* printData[MAX_CACHE_LINE];
int dataNum;
}
- (NSString*) PrintColor {
return @"红色";
}
- (void) output {
while (dataNum > 0) {
NSLog(@"打印机使用%@打印:%@", self.PrintColor, printData[0]);
dataNum--;
for (int i = 0; i < dataNum; i++) {
printData[i] = printData[i + 1];
}
}
}
- (void) addData: (NSString*) msg {
if (dataNum >= MAX_CACHE_LINE) {
NSLog(@"输出队列已满,添加失败");
} else {
printData[dataNum++] = msg;
}
}
- (NSDate*) getProduceTime {
return [[NSDate alloc] init];
}
@end
Printer类实现了Printable协议,且也实现了Printable和Printable的两个父协议中的所有方法。假如实现类没有实现协议中的PrintColor方法,编译器会提示如下警告。
#import <Foundation/Foundation.h>
#import "Printer.h"
int main(int argc, char* argv[]) {
@autoreleasepool {
//创建Printer对象
Printer* printer = [[Printer alloc] init];
//调用Printer对象的方法
[printer addData:@"疯狂iOS讲义"];
[printer addData:@"疯狂XML讲义"];
[printer output];
[printer addData:@"疯狂Android讲义"];
[printer addData:@"疯狂Ajax讲义"];
[printer output];
//创建一个Printer对象,当成Productable使用
NSObject<Productable>* p = [[Printer alloc] init];
//调用Productable协议中定义的方法
NSLog(@"%@", p.getProduceTime);
//创建一个Printer对象,当成Output使用
id<Output> out = [[Printer alloc] init];
//调用Output协议中定义的方法
[out addData:@"孙悟空"];
[out addData:@"猪八戒"];
[out output];
}
return 0;
}
输出结果如下:
程序中的两行粗体字代码没有使用Printer来定义变量,而是使用协议来定义变量,那么这些变量只能调用该协议中声明的方法,否则编译器会提示错误。
例如定义如下协议:
@protocol Output
//定义协议的方法
@optional
- (void) output;
@required
- (void) addData: (NSString*) msg;
@end
上面协议中定义了两个方法,该协议的实现类可选实现output方法,但必须实现addData:方法,否则编译器就会提示警告。
就是某个对象指定另一个对象处理某些特定任务的设计模式。通俗来说,就是“某个对象”把要做的事情委托给“另一个对象”去做。
其中“某个对象”被称作委托者,“另一个对象”被称作是被委托者,即代理。
如下图,委托方通过某种方式把任务分派出去给代理方处理,而两者之间的联系便是协议。
在程序中:一般情况下
1、 写本地方法[java] view plaincopy// 设置缩放尺寸、旋转角度 privatenative void setScale(float scale); private nativevoid setAngle(float angle); 2、 使用javah命令生成头文件。_arcamera中如何实现模型的移动
2的幂: 1 1 & 0=0 2 10 & 01=0 4 100 & 011=0 8 1000 & 0111=0 16 10000 & 01111=0#include <iostream>#include <cstdio>using namespace std;bool fun(int v){ bool flag =
http://blog.163.com/chensx_326/blog/static/1540079520078237414664/一、导入导出文本文件(txt格式)、纯数据文件(dat格式);其实都是导入导出DLM文件(*.*),需要指定分隔符号。如下(以txt为例,dat同样):1.TAB分割,第一行为变量名PROC IMPORT OUT=_sas结果集导出到excel文件怎样控制不让列名输出
urllib库中常用函数的使用#!/usr/bin/python3# -*- coding:utf-8 -*-# @Time : 2018-11-10 21:25# @Author : Manu# @Site : # @File : urllib_lib.py# @Software: PyCharmfrom urllib import requestfrom...
应用:家庭影院,安防监控,视频会议,户外荧屏,电视广播;1. HDMI1.3 over IP(网线)规格芯片组合;潜创微科技的QCW5001/QCW5002,规格:HDMI输入:1080P60,HDMI输出:1080P60;距离:200米;特色:支持红外远程遥控;优势:H.265画质好,低延时;标准的TCP/IP协议;KVM远程传输,一对多,多对一,多对多分布式矩阵,智能化网页参数设置;带宽小,兼容性好;2. HDMI1.3 over IP(无线)规格:潜创微科技的HDMI输入:1080P60;HD_qcw5001
c++,数据结构——用递归方法解决迷宫问题
在备战2020年的系统架构师考试过程中,发现了很多知识盲点,边学习边总结知识内容如下脑图,希望自己能够顺利通关,脑图会持续更新_软件架构师考试
安装gitsudo apt install git使用1.版本创建1.git add your_file2.git commit -m 'version1'3.更新版本,再次执行以上步骤2.版本回退1.可用git log,查看版本信息。2.若想回退到version1,git reset --hard HEAD^#后面的^是前几个版本就写几个或者git reset -..._ubuntu git 回退版本
Java 8提供的流的基于Lambda表达式的函数式的操作写法让人感觉很爽,笔者也一直用的很开心,直到看到了Java8 Lambda表达式和流操作如何让你的代码变慢5倍,笔者当时是震惊的,我读书少,你不要骗我。瞬间我似乎为我的Server Application速度慢找到了一个很好地锅,不过这个跟书上讲的不一样啊。于是笔者追本溯源,最后找到了始作俑者自己的分析:原文不久之前我在社区内发表了这篇文章..._java8 stream性能
一、init二、binder《ANDROID框架揭秘》第六章 - 第十章 以生动的形式讲述了binder,但是不够详细。值得参考。《Android系统源代码情景分析》第五章 描叙详细,但是不够生动。值得参考。
卷积神经网络(CNN)的原理本文主要内容:CNN的定义CNN的构成CNN的使用CNN的代码(Tensorflow)CNN的定义:CNN是一种前馈神经网络,前馈神经网络是一种最简单的神经网络。每个神经元只与前一层的神经元相连。接收前一层的输出,并输出给下一层.各层间没有反馈。 简单来说,是一种单向多层结构。同一层神经元之间没有互相连接,层间信息传达只沿一个方向进行。除..._cnn如何找到拟合函数
java 实现动态菜单,,java菜单的实现,java菜单权限实现JAVA语言实现下来菜单源程序_计算机软件及应用_IT/计算机_专业资料 暂无评价|0人阅读|0次下载|举报文档JAVA语言实现下来菜单源程序_计算机软件及应用_IT/计算机_专业......java菜单_计算机软件及应用_IT/计算机_专业资料。程序中实现菜单需要用到 ...1.菜单(菜单条组件 MenuBar、菜单组件 Menu..._java中创建菜单类menu 编写方法实现各功能 showloginmenu()方法,实现显示登录菜单