ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Objective-C 完全入门指南(learnxinyminutes-docs 西班牙语教程详解)

Objective-C 完全入门指南(learnxinyminutes-docs 西班牙语教程详解) 文档教程【免费下载链接】learnxinyminutes-docsCode documentation written as code! How novel and totally my idea!项目地址https://gitcode.com/gh_mirrors/le/learnxinyminutes-docs点击查看免费下载本指南基于 learnxinyminutes-docs 仓库中的西班牙语版 es/objective-c.md 教程对应英文原版 objective-c.md以可运行的注释代码形式完整讲解 Objective-C 的核心语法与面向对象机制。读完本文你将掌握 Objective-C 的类型系统、对象消息传递、类与属性、分类与扩展、协议、块Block以及引用计数与 ARC 内存管理能够独立读懂并编写基本的 macOS / iOS 应用代码。认识 Objective-CC 语言之上的 Smalltalk 消息机制Objective-C 是苹果公司为 macOS 与 iOS 操作系统及其框架 Cocoa、Cocoa Touch 设计的主要编程语言。它是一门通用、面向对象的语言核心思想是在 C 语言的基础上引入Smalltalk 风格的消息传递机制在 Objective-C 中你不是调用方法而是向对象发送消息。[myObject instanceMethodWithParameter:Steve Jobs]; // 发送消息这一设计贯穿整个语言从对象创建、属性访问到动态派发selector都建立在这套消息机制之上。项目约定每个语言教程以有效、带注释的代码形式呈现本指南即按这一风格组织内容。程序骨架导入、入口函数与自动释放池注释与导入Objective-C 支持//单行注释与/* ... */多行注释。使用#import导入头文件用于导入全局文件通常是框架用于导入项目内本地文件#import Foundation/Foundation.h #import MyClass.h在 Xcode 5 中若为 iOS 7.0 或 OS X 10.9 的项目启用了模块modules可以改用模块化导入语法import Foundation;main 入口与内存池程序入口是一个返回整型的main函数。函数内部先创建自动释放池来管理内存若使用自动引用计数ARC则使用autoreleasepoolint main (int argc, const char * argv[]) { NSAutoreleasePool * pool [[NSAutoreleasePool alloc] init]; // 非 ARC 时代写法 autoreleasepool { NSLog(Hello World!); // 打印字符串到控制台 } [pool drain]; // 非 ARC 下清理内存 return 0; }NSLog是 Objective-C 的控制台输出函数其格式化占位符与 C 的printf类似但增加了对象占位符%。类型与变量原始类型与对象类型原始类型与强/弱对象类型int myPrimitive1 1; long myPrimitive2 234554664565;对象声明需要在前缀加*MyClass *myObject1 nil;是强类型声明id myObject2 nil;是弱类型声明。%专门用于打印对象description是显示对象值的约定方法NSLog(% and %, myObject1, [myObject2 description]); // 输出 (null) and (null)字符串NSString 与 NSMutableStringNSString *worldString World; NSLog(Hello %!, worldString); // 输出 Hello World! NSMutableString *mutableString [NSMutableString stringWithString:Hello]; [mutableString appendString: World!]; NSLog(%, mutableString); // 输出 Hello World!NSString不可变NSMutableString是它的可变版本支持原地追加等修改操作。字面量Literals字符、整数、浮点与 BOOLObjective-C 为NSNumber提供了丰富的字面量语法覆盖字符、各种位宽的整数、浮点数与布尔值// 字符 NSNumber *theLetterZNumber Z; char theLetterZ [theLetterZNumber charValue]; // 或 Z NSLog(%c, theLetterZ); // 整数带 U/L 后缀区分无符号与长整型 NSNumber *fortyTwoNumber 42; int fortyTwo [fortyTwoNumber intValue]; // 或 42 NSLog(%i, fortyTwo); NSNumber *fortyTwoUnsignedNumber 42U; unsigned int fortyTwoUnsigned [fortyTwoUnsignedNumber unsignedIntValue]; // 或 42 NSLog(%u, fortyTwoUnsigned); NSNumber *fortyTwoShortNumber [NSNumber numberWithShort:42]; short fortyTwoShort [fortyTwoShortNumber shortValue]; // 或 42 NSLog(%hi, fortyTwoShort); NSNumber *fortyOneShortNumber [NSNumber numberWithShort:41]; unsigned short fortyOneUnsigned [fortyOneShortNumber unsignedShortValue]; // 或 41 NSLog(%u, fortyOneUnsigned); NSNumber *fortyTwoLongNumber 42L; long fortyTwoLong [fortyTwoLongNumber longValue]; // 或 42 NSLog(%li, fortyTwoLong); NSNumber *fiftyThreeLongNumber 53L; unsigned long fiftyThreeUnsigned [fiftyThreeLongNumber unsignedLongValue]; // 或 53 NSLog(%lu, fiftyThreeUnsigned); // 浮点F 后缀为 float否则为 double NSNumber *piFloatNumber 3.141592654F; float piFloat [piFloatNumber floatValue]; // 或 3.141592654f NSLog(%f, piFloat); // 输出 3.141592654 NSLog(%5.2f, piFloat); // 输出 3.14宽度 5、两位小数 NSNumber *piDoubleNumber 3.1415926535; double piDouble [piDoubleNumber doubleValue]; // 或 3.1415926535 NSLog(%f, piDouble); NSLog(%4.2f, piDouble); // 输出 3.14 // BOOL NSNumber *yesNumber YES; NSNumber *noNumber NO; BOOL yesBool YES; BOOL noBool NO; NSLog(%i, yesBool); // 输出 1NSLog对应的格式说明符分别为%c字符、%iint、%uunsigned int、%hishort、%lilong、%luunsigned long、%f浮点——这与 C 语言保持一致。NSLog还支持宽度精度控制例如%5.2f会按宽度 5、两位小数输出。高精度定点数NSDecimalNumber当float/double的精度不够时如金额计算可以使用定点数类NSDecimalNumber。它不能使用标准 - * /运算符而是提供自己的运算方法NSDecimalNumber *oneDecNum [NSDecimalNumber decimalNumberWithString:10.99]; NSDecimalNumber *twoDecNum [NSDecimalNumber decimalNumberWithString:5.002]; [oneDecNum decimalNumberByAdding:twoDecNum]; [oneDecNum decimalNumberBySubtracting:twoDecNum]; [oneDecNum decimalNumberByMultiplyingBy:twoDecNum]; [oneDecNum decimalNumberByDividingBy:twoDecNum]; NSLog(%, oneDecNum); // 输出 10.99NSDecimalNumber 不可变集合数组、字典与集合NSArray / NSMutableArrayNSArray可容纳不同类型的对象必须是 Objective-C 对象支持下标访问NSArray *anArray [1, 2, 3, 4]; NSNumber *thirdNumber anArray[2]; NSLog(Third number %, thirdNumber); // 输出 Third number 3 NSMutableArray *mutableArray [NSMutableArray arrayWithCapacity:2]; [mutableArray addObject:Hello]; [mutableArray addObject:World]; [mutableArray removeObjectAtIndex:0]; NSLog(%, [mutableArray objectAtIndex:0]); // 输出 WorldNSMutableArray允许增删元素使用方便但性能不如NSArray。NSDictionary / NSMutableDictionary使用{key : value}字面量语法NSDictionary *aDictionary { key1 : value1, key2 : value2 }; NSObject *valueObject aDictionary[A Key]; NSLog(Object %, valueObject); // 输出 Object (null)键不存在返回 nil NSMutableDictionary *mutableDictionary [NSMutableDictionary dictionaryWithCapacity:2]; [mutableDictionary setObject:value1 forKey:key1]; [mutableDictionary setObject:value2 forKey:key2]; [mutableDictionary removeObjectForKey:key1];NSSet / NSMutableSet集合自动去重不保证顺序NSSet *set [NSSet setWithObjects:Hello, Hello, World, nil]; NSLog(%, set); // 输出 {(Hello, World)}顺序可能不同 NSMutableSet *mutableSet [NSMutableSet setWithCapacity:2]; [mutableSet addObject:Hello]; [mutableSet addObject:Hello]; NSLog(%, mutableSet); // 输出 {(Hello)}运算符与 C 语言一致Objective-C 的运算符行为与 C 语言完全相同2 5; // 7 4.2f 5.1f; // 9.3f 3 2; // 0假 3 ! 2; // 1真 1 1; // 1逻辑与 0 || 1; // 1逻辑或 ~0x0F; // 0xF0按位取反 0x0F 0xF0; // 0x00按位与 0x01 1; // 0x02按位左移 1 位在条件判断中0 表示假NO非 0 表示真YES。控制结构if、switch、循环与异常if-else 与 switchif (NO) { NSLog(I am never run); } else if (0) { NSLog(I am also never run); } else { NSLog(I print); } switch (2) { case 0: { NSLog(I am never run); } break; case 1: { NSLog(I am also never run); } break; default: { NSLog(I print); } break; }三种循环// whileii 先使用值再自增 int ii 0; while (ii 4) { NSLog(%d,, ii); } // 输出 0, 1, 2, 3, // for int jj; for (jj 0; jj 4; jj) { NSLog(%d,, jj); } // 输出 0, 1, 2, 3, // foreach快速枚举 NSArray *values [0, 1, 2, 3]; for (NSNumber *value in values) { NSLog(%,, value); } // 输出 0, 1, 2, 3, // 也可以使用 id 遍历任意 Objective-C 对象 for (id item in values) { NSLog(%,, item); }异常处理与 NSErrortry { throw [NSException exceptionWithName:FileNotFoundException reason:File Not Found on System userInfo:nil]; } catch (NSException * e) { // 使用 catch (id exceptionName) 可捕获所有对象 NSLog(Exception: %, e); } finally { NSLog(Finally. Time to clean up.); } // 输出 Exception: File Not Found on System // Finally. Time to clean up.此外NSError对象常用于函数参数用来承载用户操作错误信息NSError *error [NSError errorWithDomain:Invalid email. code:4 userInfo:nil];对象模型alloc/init 与消息传递创建对象需要两步分配内存alloc与初始化init两步都完成后对象才完全可用MyClass *myObject [[MyClass alloc] init];Objective-C 的面向对象模型基于向实例发送消息。教程原文强调在 Objective-C 中你不是调用方法而是发送消息——这是理解后续 selector 动态派发的基础。类与函数interface 与 implementation类的声明MyClass.h类声明语法如下interface ClassName : ParentClassName ImplementedProtocols { type name; // 变量声明 } property type name; // 属性声明 -/ (type)MethodDeclaration; // 方法声明 end完整的示例interface MyClass : NSObject MyProtocol // NSObject 是 Objective-C 的基类 { int count; // 默认 protected 访问 private id data; // private 访问更常见于实现文件中声明 NSString *name; } property int propInt; // setter 方法名默认为 setPropInt property (copy) id copyId; // (copy) 赋值时拷贝对象 property (readonly) NSString *roString; // (readonly) 不能在 interface 外赋值 // 自定义 getter/setter 名称 property (getterlengthGet, setterlengthSet:) int length; // 方法声明 (NSString *)classMethod; // 类方法 (MyClass *)myClassFromHeight:(NSNumber *)defaultHeight; - (NSString *)instanceMethodWithParameter:(NSString *)string; // - 实例方法 - (NSNumber *)methodAParameterAsString:(NSString*)string andAParameterAsNumber:(NSNumber *)number; - (id)initWithDistance:(int)defaultDistance; // 带参数的构造方法 endObjective-C 的方法名极具描述性约定根据参数来命名方法如methodAParameterAsString:andAParameterAsNumber:。属性的访问setter/getter 与点语法property会自动生成 setter 方法默认为set 属性名MyClass *myClass [[MyClass alloc] init]; [myClass setCount:10]; NSLog(%d, [myClass count]); // 输出 10 // 使用自定义 getter/setter [myClass lengthSet:32]; NSLog(%i, [myClass lengthGet]); // 输出 32 // 点语法更便捷 myClass.count 45; NSLog(%i, myClass.count); // 输出 45类方法与实例方法调用NSString *classMethodString [MyClass classMethod]; MyClass *classFromName [MyClass myClassFromName:Hello]; MyClass *myClass [[MyClass alloc] init]; NSString *stringFromInstanceMethod [myClass instanceMethodWithParameter:Hello];Selector方法的动态表示SEL是方法选择器的数据类型selector()根据方法名返回选择器。Selector 用于动态调用方法、把方法作为参数传递或保存为变量SEL selectorVar selector(methodAParameterAsString:andAParameterAsNumber:); if ([myClass respondsToSelector:selectorVar]) { // 检查类是否包含该方法 // performSelector 只能携带一个对象参数需要把所有参数打包进一个对象 NSArray *arguments [NSArray arrayWithObjects:Hello, 4, nil]; [myClass performSelector:selectorVar withObject:arguments]; // 调用方法 } else { // NSStringFromSelector() 返回给定 selector 对应的方法名字符串 NSLog(MyClass does not have method: %, NSStringFromSelector(selectorVar)); }注意respondsToSelector:用于在动态调用前确认对象确实实现了该方法避免运行时崩溃。类的实现MyClass.mimplementation MyClass { long distance; // 私有访问实例变量 NSNumber *height; } // 访问接口文件中的公开变量_ 变量名 _count 5; // 引用 MyClass 接口中的 int count distance 18; // 引用实现文件中的 long distance // 在实现文件中使用 property 变量用 synthesize 创建访问器变量 synthesize roString _roString; // 现在 _roString 可用于 implementation // 在调用任何类方法或实例化任何对象之前调用 (void)initialize { if (self [MyClass class]) { distance 0; } } // initialize 的对应方法当对象引用计数归零时调用 - (void)dealloc { [height release]; // 非 ARC 时必须手动释放对象类型变量 [super dealloc]; // 并调用父类的 dealloc } // 默认构造方法 - (id)init { if ((self [super init])) { // super 访问父类方法 self.count 1; // self 让对象调用自身 } return self; } // 带参数的构造方法 - (id)initWithDistance:(int)defaultDistance { distance defaultDistance; return self; } (NSString *)classMethod { return Some string; } (MyClass *)myClassFromHeight:(NSNumber *)defaultHeight { height defaultHeight; return [[self alloc] init]; } - (NSString *)instanceMethodWithParameter:(NSString *)string { return New string; } - (NSNumber *)methodAParameterAsString:(NSString*)string andAParameterAsNumber:(NSNumber *)number { return 42; } // Objective-C 没有私有方法声明但可以模拟 // 只在 implementation 中定义、不在 interface 中声明即可。 - (NSNumber *)secretPrivateMethod { return 72; } [self secretPrivateMethod]; // 调用私有方法 // MyProtocol 中声明的方法 - (void)myProtocolMethod { // statements } end分类Categories为既有类添加方法分类是一组用于扩展已有类的方法目的是组织代码。它不同于子类子类用于改变对象的功能分类用于为对象添加功能。分类允许为组织目的向既有类添加方法扩展 Objective-C 自带类如NSString加入自定义方法为类创建 protected / private 方法。注意不要用分类覆盖基类方法——即使技术上可行。覆盖方法可能导致不同分类之间产生编译期错误也违背了分类只添加功能的初衷。覆盖方法应使用子类。以一个Car基类为例// Car.h interface Car : NSObject property NSString *make; property NSString *color; - (void)turnOn; - (void)accelerate; end // Car.m #import Car.h implementation Car synthesize make _make; synthesize color _color; - (void)turnOn { NSLog(Car is on.); } - (void)accelerate { NSLog(Accelerating.); } end若只想为Car增加清洗功能而不是创建Truck子类就使用分类。分类的接口文件命名约定为基类名分类名.h// CarClean.h #import Car.h // 必须导入要扩展的基类 interface Car (Clean) // 分类名写在 () 内紧跟基类名 - (void)washWindows; // 新增方法 - (void)wax; end // CarClean.m #import CarClean.h // 导入分类的 interface 文件 implementation Car (Clean) - (void)washWindows { NSLog(Windows washed.); } - (void)wax { NSLog(Waxed.); } end任何Car实例都能使用分类方法只需导入分类头文件#import CarClean.h #import Car.h int main (int argc, const char * argv[]) { autoreleasepool { Car *mustang [[Car alloc] init]; mustang.color Red; mustang.make Ford; [mustang turnOn]; // 使用 Car 基类方法 [mustang washWindows]; // 使用 Car 的 Clean 分类方法 } return 0; }用分类模拟 protected 方法Objective-C 没有 protected 方法声明但可以模拟创建一个包含所有 protected 方法的分类只把它导入某个属于Car类的implementation文件// CarProtected.h命名 Protected 以便记住这些是受保护方法 interface Car (Protected) - (void)lockCar; // 这里列出的方法只能由 Car 对象创建 end // 使用受保护方法导入分类然后实现其方法 #import CarProtected.h // 记住只导入到 implementation 文件 implementation Car - (void)lockCar { NSLog(Car locked.); // Car 的实例无法调用 lockCar因为它不在 interface 中 } end扩展Extensions重写属性与方法扩展允许你覆盖公开 interface 中属性的访问级别和方法。扩展与类的implementation位于同一文件中语法是在基类名后加空括号()// Shape.h interface Shape : NSObject property (readonly) NSNumber *numOfSides; - (int)getNumOfSides; end // Shape.m —— 扩展与 implementation 同文件 #import Shape.h interface Shape () // () 声明扩展 property (copy) NSNumber *numOfSides; // 把 numOfSides 改为 copy 而非 readonly - (NSNumber)getNumOfSides; // 让 getNumOfSides 返回 NSNumber 而非 int - (void)privateMethod; // 也可以在扩展中创建新的私有方法 end implementation Shape synthesize numOfSides _numOfSides; - (NSNumber)getNumOfSides { // 扩展中的声明必须在 implementation 中实现 return _numOfSides; } - (void)privateMethod { NSLog(Private method created by extension. Shape instances cannot call me.); } end扩展与分类的区别扩展可以改变既有属性的行为如readonly→copy并声明私有方法且其声明必须在同文件的implementation中实现。协议Protocols定义接口契约协议声明可供任何类实现的方法。协议本身不是类它只定义一份其他对象负责实现的接口。协议文件示例// CarUtilities.h protocol CarUtilities NSObject // NSObject 包含的另一个协议名 property BOOL engineOn; // 采纳协议的类必须 synthesize 所有 property - (void)turnOnEngine; // 并实现所有方法 end实现协议的类#import CarUtilities.h interface Car : NSObject CarUtilities // 协议名写在 中 - (void)turnOnEngineWithUtilities:(id CarUtilities)car; // 协议也可作为数据类型 end implementation Car : NSObject CarUtilities synthesize engineOn _engineOn; // 为 engineOn property 创建 synthesize - (void)turnOnEngine { // 协议的实现方式完全由类自己决定 _engineOn YES; // 协议只要求实现不规定如何实现 } - (void)turnOnEngineWithCarUtilities:(id CarUtilities)objectOfSomeKind { [objectOfSomeKind engineOn]; // 可以访问对象的变量 [objectOfSomeKind turnOnEngine]; // 和方法 [objectOfSomeKind engineOn]; // 是否为 YES 由实现类决定 } end使用协议与运行时检查Car *carInstance [[Car alloc] init]; [carInstance setEngineOn:NO]; [carInstance turnOnEngine]; if ([carInstance engineOn]) { NSLog(Car engine is on.); // 输出 Car engine is on. } // 在调用协议方法前务必检查对象是否遵循协议 if ([myClass conformsToProtocol:protocol(CarUtilities)]) { NSLog(This does not run as the MyClass class does not implement the CarUtilities protocol.); } else if ([carInstance conformsToProtocol:protocol(CarUtilities)]) { NSLog(This does run as the Car class implements the CarUtilities protocol.); }其他要点分类也可以实现协议interface Car (CarCategory) CarUtilities一个类可以实现多个协议interface Car : NSObject CarUtilities, CarCleaning当两个协议互相依赖时必须向前声明forward-declare以避免编译器错误#import Brother.h protocol Brother; // 向前声明缺少它会触发编译错误 protocol Sister NSObject - (void)beNiceToBrother:(id Brother)brother; end // Sister 依赖 Brother而 Brother 又依赖 Sister #import Sister.h protocol Sister; // 这行终止递归解决问题 protocol Brother NSObject - (void)beNiceToSister:(id Sister)sister; end块Blocks可作数据使用的代码段块是类似函数的代码段可以像数据一样被使用、保存和传递。声明与调用int (^addUp)(int n); // 声明一个存储块的变量 void (^noParameterBlockVar)(void); // 无参数的块变量 int outsideVar 17; // 若在声明 addUp 之后修改 outsideVar块内看到的仍是 17 __block long mutableVar 3; // __block 使变量在块内可写 addUp ^(int n) { // 去掉 (int n) 即得到无参数块 NSLog(You may have as many lines in a block as you would like.); NSSet *blockSet; // 块内也可以声明局部变量 mutableVar 32; // 给 __block 变量赋新值 return n outsideVar; // return 语句可选 }; int result addUp(10 16); // 带参数调用块块的重要特性块能访问同一作用域的变量但默认是只读的且块拿到的值是创建块时的变量值__block修饰符让变量在块内可写块通常作为参数传给函数用于稍后调用或回调callback。implementation BlockExample : NSObject - (void)runBlock:(void (^)(NSString))block { NSLog(Block argument returns nothing and takes in a NSString object.); block(Argument given to block to execute.); // 调用块 } end内存管理从引用计数到 ARCObjective-C 不使用垃圾回收而是采用引用计数。只要对象至少被一个引用持有即拥有该对象对象就可用每次拥有引用计数 1每次 release 引用计数 -1计数归零时对象从内存中移除。交互模式遵循(1) 创建对象 → (2) 使用对象 → (3) 释放对象。手动引用计数MRCMyClass *classVar [MyClass alloc]; // alloc 将 classVar 引用计数设为 1返回对象指针 [classVar release]; // 将 classVar 的引用计数减 1 // retain取得既有对象的所有权引用计数 1返回对象指针 MyClass *newVar [classVar retain]; // 即使 classVar 被 release对象仍在内存中因为 newVar 拥有它 [classVar autorelease]; // 在 autoreleasepool 块结束时释放所有权返回对象指针property也支持retain与assign属性property (retain) MyClass *instance; // 释放旧值、retain 新值强引用 property (assign) NSSet *set; // 指向新值而不 retain/release 旧值弱引用自动引用计数ARC鉴于手动内存管理容易出错Xcode 4.2 与 iOS 4 引入了ARCAutomatic Reference Counting。ARC 是编译器特性会自动插入retain、release、autorelease因此使用 ARC 时禁止手动调用这三个方法MyClass *arcMyClass [[MyClass alloc] init]; // ... 使用 arcMyClass 的代码 // 非 ARC 下结束使用后需调用 [arcMyClass release] // ARC 下无需手动释放编译器会自动插入释放语句对应assign/retainARC 下使用weak/strongproperty (weak) MyClass *weakVar; // weak 不拥有对象原实例引用计数归零时 // weakVar 自动被赋为 nil避免应用崩溃 property (strong) MyClass *strongVar; // strong 拥有对象确保对象驻留内存普通变量非property使用以下修饰符__strong NSString *strongString; // 默认值变量在离开作用域前一直驻留内存 __weak NSSet *weakSet; // 对既有对象的弱引用对象释放后 weakSet 被置为 nil __unsafe_unretained NSArray *unsafeArray; // 类似 __weak但对象释放后 // unsafeArray 不会被置为 nil悬垂风险教程在仓库中的位置与协作规范本教程是 learnxinyminutes-docs 仓库多语言文档体系的一部分英文原版位于 objective-c.md西班牙语版即本文依据的 es/objective-c.md另有 zh-cn/objective-c.md、fr/objective-c.md、ru/objective-c.md、vi/objective-c.md、tr/objective-c.md 等多个语言版本。每篇文档头部都包含 YAML frontmattercontributors作者信息、translators译者信息、filename代码文件名等仓库中的 lint/frontmatter.py 脚本会校验这些元数据的合法键名与格式CONTRIBUTING.md 则规定了 80 字符行长、以代码示例优先、面向有经验的程序员等写作规范。这些机制保证了各语言教程在结构上保持一致、可直接对照阅读。进一步阅读作为学习路线的延伸建议继续阅读仓库中以下相关主题Objective-C 中文版教程与本文对应的简体中文版本便于对照理解C 语言教程Objective-C 的语法基础Swift 教程苹果生态的现代后继语言便于对比两种语言的设计差异Rust 教程、Go 教程同为系统级/通用编程语言可横向比较消息传递与所有权模型等不同设计赞分享文档教程【免费下载链接】learnxinyminutes-docsCode documentation written as code! How novel and totally my idea!项目地址https://gitcode.com/gh_mirrors/le/learnxinyminutes-docs点击查看免费下载相关推荐Scala 快速入门实战指南基于 learnxinyminutes-docs 西班牙语教程的完整语法精讲Scala 快速入门实战指南基于 learnxinyminutes docs 西班牙语教程的完整语法精讲 本指南以仓库中的 es/scala.md https文档教程CoffeeScript 入门指南从西班牙语教程看编译到 JavaScript 的语法速览learnxinyminutes-docsCoffeeScript 入门指南从西班牙语教程看编译到 JavaScript 的语法速览learnxinyminutes docs 导读 本文以 lea文档教程使用 R 语言完成统计分析learnxinyminutes-docs 西班牙语版 R 教程全解使用 R 语言完成统计分析learnxinyminutes docs 西班牙语版 R 教程全解 本篇技术指南以 es/r.md https://link.gi文档教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表