• 【OC基础】01-类和对象


    类定义

    在OC中,一般用二个文件描述一个类,一个是.h文件,一个是.m文件爱你:

    1>:.h文件是类的声明文件,用于声明变量和方法。类的声明使用关键字@interface和@end。

    2>:.m文件是类的实现文件,用于实现.h类中声明的方法。类的实现使用关键字@implementation和@end。

    方法

    1> 方法的声明和实现,都必须以 + 或者 - 开头

    • + 表示类方法(静态方法)
    • - 表示对象方法(动态方法)

    2> 在.h中声明的所有方法作用域都是public类型,不能更改

    成员变量

    成员变量的常用作用域有3种:

    1> @public 全局都可以访问
    2> @protected 只能在类内部和子类中访问
    3> @private 只能在类内部访问

    方法和属性

    1.Student.h类的声明文件

     1 #import <Foundation/Foundation.h>
     2 
     3 @interface Student : NSObject {
     4     
     5     int age;
     6     @public
     7     int no;
     8     int score;
     9     
    10     @protected
    11     float height;
    12     
    13     @private
    14     float weight;
    15 }
    16 - (int)age;
    17 - (void)setAge:(int)newAge;
    18 - (void)setAge:(int)newAge :(float)newHeight;
    19 @end

    1>第3行:用@interface声明一个类Student,后面紧跟着的:表示继承与NSObject

    2>第5行:定义了一个int类型的成员变量age,age的默认作用域是@protected,即可以在Student类内部和子类中访问

    3>第16行:声明了age的get方法,方法名就叫做age,OC建议get方法的名字跟成员变量保持一致。- 表示这是一个动态方法( + 则表示静态方法),动态方法属于对象,静态方法属于类。

    4>地18行:方法的方法名是setAge:andHeight:

    2.Student.m的实现文件

     1 #import "Student.h"
     2 
     3 @implementation Student
     4 
     5 - (int)age {
     6     NSLog(@"age...");
     7     return age;
     8 }
     9 
    10 - (void) setAge:(int)newAge {
    11     NSLog(@"setage...");
    12     age = newAge;
    13 }
    14 
    15 - (void) setAge:(int)newAge :(float)newHeight {
    16     age = newAge;
    17     height = newHeight;
    18 }
    19 
    20 @end

    第5行和第10行和15行实现了Student.h中声明的方法

    在Java或者C#中有一个属性的概念,通常访问成员变量不是直接访问,而是访问这些属性。OC中的属性和Java中的类似,都是通过get/set方法实现的,不过有一点不同的是,OC的get方法通常直接使用变量名。

     1 #import <Foundation/Foundation.h>
     2 #import "Student.h"
     3 int main(int argc, const char * argv[])
     4 {
     5 
     6     @autoreleasepool {
     7         
     8         // insert code here...
     9         Student *stu = [[Student alloc]init];
    10         stu.age = 15;
    11         NSLog(@"......");
    12         
    13         int age1 = stu.age;
    14         NSLog(@"......");
    15         
    16         stu->no = 120;
    17         [stu setAge:100];
    18         int age = [stu age];
    19         
    20         NSLog(@"student no=%i,age is=%i,age1=%i",stu->no,age,age1);
    21         NSLog(@"Hello, World!");
    22         [stu release];
    23     }
    24     return 0;
    25 }

    1>第9行:创建一个Student类对象,分配空间并初始化

    2>第10行获取和设置age的值,等价于调用[stu setAge:15]和int age = [stu age]。点语法的本质是函数调用

    2>第16行:公共成员变量no,如果不是公共变量,不能像这样直接访问。注意访问方式:对象->成员变量

    通过上面的例子我们可以看出,定义属性的代码都是非常类似的,所以在OC中提供了更简单的方法,OC中可以通过声明@property,同时通过@synthesize自动生成get/set方法。

    Student.h文件

    1 #import <Foundation/Foundation.h>
    2 
    3 @interface Student : NSObject
    4 
    5 @property NSString *name;
    6 @property NSString *birth;
    7 @property float grade;
    8 @end

    Student.m文件

    1 #import "Student.h"
    2 
    3 @implementation Student
    4 
    5 @synthesize name;
    6 @synthesize birth=_birth;
    7 
    8 @end

    main.m文件

     1 #import <Foundation/Foundation.h>
     2 #import "CateStudent.h"
     3 int main(int argc, const char * argv[])
     4 {
     5 
     6     @autoreleasepool {
     7         
     8         // insert code here...
     9         Student *stu = [[Student alloc]init];
    10         stu.name=@"zhangsan";
    11         stu.birth=@"1993-09-12";
    12         stu.grade=99;
    13         NSLog(@"name=%@ and birth=%@ grade=%f",stu.name,stu.birth,stu.grade);
    14     }
    15     return 0;
    16 }

    上面的例子包含了使用属性扩展的三种情况:

    1>只声明一个属性a,不使用@synthesize实现(如grade):此时编译器会使用_a作为属性的成员变量(如果没有_a变量,编译器会自动生成一个私有的成员变量_a)

    2>声明一个属性a,使用@synthesize实现,但是没有指定使用的成员变量(如name):此时编译器会使用a作为属性的成员变量(如果没有a变量,编译器会自动生成一个私有的成员变量a)

    3>声明一个属性a,使用@synthesize实现,指定使用的成员变量(如birth):此时编译器会使用指定的成员变量

    其实上面的过程在本质上也是生成对应的get/set方法,如果声明了@property而且在.m文件里自定义了实现方法,就会使用自定义方法。

    self关键字

    在C++中有一个this指针表示当前对象,在OC中也有一个self关键字表示当前对象或者类本身。

    Student.h文件:

     1 #import <Foundation/Foundation.h>
     2 
     3 @interface Student : NSObject
     4 
     5 @property NSString *name;
     6 @property float age;
     7 - (void)setName:(NSString *)name andAge:(int)age;
     8 +(void)print;
     9 +(void)showMsg;
    10 @end

    Student.m文件:

     1 #import "Student.h"
     2 
     3 @implementation Student
     4 
     5 -(void)setName:(NSString *)name andAge:(int)age{
     6     self.name = name;//调用setName
     7     self.age = age;//调用setAge
     8 }
     9 
    10 +(void)print{
    11     NSLog(@"......");
    12 }
    13 
    14 +(void)showMsg{
    15     [self print];
    16 }
    17 @end

    main.m文件:

     1 #import <Foundation/Foundation.h>
     2 #import "CateStudent.h"
     3 int main(int argc, const char * argv[])
     4 {
     5 
     6     @autoreleasepool {
     7         
     8         // insert code here...
     9         Student *stu = [[Student alloc]init];
    10         [stu setName:@"zhansan" andAge:12];
    11         NSLog(@"name=%@ and age=%f",stu.name,stu.age);
    12         [Student showMsg];
    13     }
    14     return 0;
    15 }

    在这个例子中self可以调用静态方法也可以调用动态方法。但是调用的本质是不一样的,动态方法调用既实例里面的self,是对象的首地址;类方法里面的self,是Class。

    构造方法

    在对象的创建时往往需要初始化调用init方法,接下来我们看下如何创建init方法:

    Student.h文件:

     1 #import <Foundation/Foundation.h>
     2 
     3 @interface Student : NSObject
     4 
     5 @property NSString *name;
     6 @property float age;
     7 -(id)initWithName:(NSString*)name andAge:(int)age;
     8 
     9 +(id)stuWithName:(NSString*)name andAge:(int)age;
    10 +(void)print;
    11 +(void)showMsg;
    12 @end

    Student.m文件:

     1 import "Student.h"
     2 
     3 @implementation Student
     4 
     5 -(id)initWithName:(NSString*)name andAge:(int)age{
     6     if(self=[super init]){
     7         self.name=name;
     8         self.age=age;
     9     }
    10     return self;
    11 }
    12 
    13 +(id)stuWithName:(NSString*)name andAge:(int)age{
    14     //类方法不能直接访问实例方法,但是可以通过创建对象访问实例方法
    15     Student *s = [[Student alloc]initWithName:name andAge:age];
    16     return s;
    17 }
    18 
    19 +(void)print{
    20     NSLog(@"......");
    21 }
    22 +(void)showMsg{
    23     [self print];
    24 }
    25 @end

    main.m文件:

     1 #import <Foundation/Foundation.h>
     2 #import "CateStudent.h"
     3 int main(int argc, const char * argv[])
     4 {
     5 
     6     @autoreleasepool {
     7         
     8         // insert code here...
     9         Student *stu = [[Student alloc]initWithName:@"lisi" andAge:11];
    10         NSLog(@"name=%@ and age=%f",stu.name,stu.age);
    11         Student *stu1 = [Student stuWithName:@"wanger" andAge:14];
    12         NSLog(@"name=%@ and age=%f",stu1.name,stu1.age);
    13         [Student showMsg];
    14     }
    15     return 0;
    16 }

    description方法

    在Java中基本每个类都有一个toString()方法用于打印一个对象的信息,在OC中这个方法叫description,这个方法通常用于调试:

    1 #import "Student.h"
    2 
    3 @implementation Student
    4 
    5 -(NSString*)description{
    6     return [NSString stringWithFormat:@"{name:%@,age:%f}",self.name,self.age];
    7 }
    8 @end

    默认情况下如果我们不重写description方法,输出内容是类名和地址。

    总结

    1、- 表示对象方法(动态方法),+ 表示类方法(静态方法)

    2、.语法的本质是get或者set函数调用

    3、静态方法中不能直接调用对象方法,但是可以创建对象后调用此方法

  • 相关阅读:
    mvn地址
    .net 通过蓝牙调用佳博标签打印机
    DockerDesktop使用自带的k8s v1.24.0 使用kubectl获取不到token的问题
    ubuntu firefox install video code
    发送消息的方式在enum中指定
    6pom里配置阿里云仓库
    7idea 手动配置运行 spring 项目
    10idea手动配置run vue
    9写一个最简单的测试接口
    2VUE布局
  • 原文地址:https://www.cnblogs.com/desheng-Win/p/4471741.html
Copyright © 2020-2023  润新知