继承、初始化方法、便利构造器

本文详细介绍了面向对象编程中的类继承机制,包括继承的概念、self与super的区别、初始化方法与构造器的使用,以及如何通过便利构造器创建对象。通过实例分析,展示了在不同类层次中方法调用的过程,以及如何在子类中覆盖或重用父类的方法。

 

…………………………………………………………………………………………………………………………………………………………….

 

//继承:子类会继承父类所有实例变量以及方法

 //self:  谁调用此方法,self就是谁。

// self: 调用方法,首先在当前类寻找实现,如果有实现,直接调用,如果没有,去父类中寻找实现,找到即执行完毕。

  //super 是编译器指令,不是对象。

 //  super调用方法,直接去父类中寻找实现,执行完父类的实现,再执行子类的实现,完毕。

 //指定初始化方法:

// 一定会调用父类的指定初始化方法

//  一般来说参数最多

 

//便利构造器

//  内部实现即调用了指定初始化方法。

 

// main.m

 

#import<Foundation/Foundation.h>

#import "Person.h"

#import "Student.h"

#import "Car.h"

#import "AudiCar.h"

#import "CollegeStudent.h"

 

int main(intargc, const char * argv[]) {

   @autoreleasepool {

//       Person *person = [[Person alloc]initWithName:@"ylc"gender:@"m" age:20];

//       [personsetName:@"zrt" gender:@"w" age:21];

//       [personsayHi];

//       

//       Student *stu = [[Student alloc]initWithName:@"ee"gender:@"m" age:100 num:2];

//       [stusetName:@"sds" gender:@"fs" age:22];

//       //  如果当前类有重新实现,就是用当前类的重新实现方法,如果没有重新实现,使用父类的方法

//       [stusayHi];

 

CollegeStudent *collegestudent =[[CollegeStudentalloc]initWithName:@"yzz" gender:@"m"age:22 num:1 major:@"electricity"];

       // 向college发送sayHi消息

       [collegestudentsayHi];

 

       // 利用便利构造器发送一个消息

       // 便利构造器是一个 + 方法,因此用类名调用

       // 返回值类型为 Person *,因此用  Person * 型变量接受。

       Person *p = [Person personWithName:@"df" gender:@"f"age:33];

 

 

    }

return 0;

}

 

 

 

// Person.m

#import "Person.h"

@implementation Person

 

// 指定初始化方法: 一般参数最多,而且会调用父类的初始化方法。

- (instancetype)initWithName:(NSString*)name gender:(NSString *)gender age:(int)age{

self = [super init];

if (self) {

//       _name = name;

//       _gender = gender;

//       _age = age;

       [selfsetName:namegender:genderage:age];

    }

return self;

}

 

- (void)setName:(NSString *)namegender:(NSString *)gender age:(int)age{

   _name = name;

   _gender = gender;

   _age = age;

}

 

- (NSString *)name{

return _name;

}

 

- (int)age{

return _age;

}

 

- (NSString *)gender{

return _gender;

}

 

- (void)sayHi{

NSLog(@"%@正在唱小苹果",_name);

}

 

// 便利构造器的实现

+ (Person *)personWithName:(NSString *)namegender:(NSString *)gender age:(int)age{

   Person *p = [[Person alloc]initWithName:namegender:genderage:age];

return p;

 

}

@end

 

 

//  Student.m

#import "Student.h"

 

@implementation Student

 

- (instancetype)initWithName:(NSString*)name gender:(NSString *)gender age:(int)age num:(int)num{

//   _name = name;

//   _gender = gender;

//   _age = age;

//   _num = num;

   //调用父类的初始化方法

self = [super initWithName:namegender:genderage:age];

if (self) {

       _num = num;

    }

return self;

}

 

- (void)sayHi{

   //  这里不能向self发送sayHi消息,会造成递归调用。

   //向父类发送sayHi消息,super不是一个对象。

   [supersayHi];

NSLog(@"%@唱最炫民族风",_name);

}

 

 

@end

 

// CollegeStudent.m

#import "CollegeStudent.h"

 

@implementationCollegeStudent

 

- (instancetype)initWithName:(NSString*)name gender:(NSString *)gender age:(int)age num:(int)num major:(NSString*)major{

//   _name = name;

//   _gender = gender;

//   _age = age;

//   _num = num;

//   _major = major;

self = [superinitWithName:namegender:genderage:agenum:num];

if (self) {

       _major = major;

    }

return self;

}

 

- (void)setMajor:(NSString *)major{

   _major = major;

}

 

- (NSString *)major{

return _major;

}

//子类可以重写⽗类的方法,即:子类既有⾃己的实现,⼜有⽗类继承下来的实现,如果想使用⽗类的实现,向super发送消息。

- (void)sayHi{

     [supersayHi];

NSLog(@"123");

}

@end

 

<think>我们正在讨论构造器属于类方法还是实例方法。根据之前的讨论和引用材料,我们可以总结如下: 1. 构造器(Constructor)在Java中是一个特殊的方法,用于初始化新创建的对象。 2. 构造器在创建对象时通过`new`关键字调用,且只执行一次。 3. 从引用[1]中我们知道:构造器总是伴随着new操作一起调用,对象一建立,构造器就运行且只运行一次。一般方法可以被调用多次。 4. 引用[2]中提到了类方法(静态方法)和实例方法:类方法不依赖于对象,而实例方法必须通过对象调用。 5. 引用[4]提到:构造方法在实例化对象时被调用,用于初始化成员变量。 那么,构造器属于哪一种方法呢? 分析: - 构造器不是类方法(静态方法),因为类方法不需要实例就可以调用(通过类名),而构造器必须通过`new`来调用,并且是在创建实例的时候调用。因此,构造器不属于类方法。 - 构造器也不是实例方法,因为实例方法是在对象已经创建之后才能调用的方法,而构造器是在创建对象的过程中调用的,它负责创建对象并初始化。在构造器执行完毕之前,对象还没有完全创建成功。 实际上,构造器是一种特殊的方法,它既不是类方法也不是实例方法。它是对象创建过程中的一个必要步骤。在Java中,构造器不属于任何一类方法,而是单独的一类。 但是,我们可以从调用的角度来看: - 构造器在调用时,还没有对象实例(正在创建),所以不能像实例方法那样通过对象调用。 - 构造器也不能通过类名直接调用(除了在`new`后面,或者通过反射调用,但反射调用实际上也是创建实例的过程)。 因此,结论是:构造器既不是类方法(静态方法)也不是实例方法。它是一种特殊的方法,专门用于对象的初始化。 另外,在引用[2]中,Objective-C中提到了“便利构造器”,它是一种类方法,因为便利构造器是通过类方法返回一个实例,但这与Java中的构造器不同。在Java中,构造器不是类方法。 所以,回答用户的问题:构造器不属于类方法,也不属于实例方法,它是独立的一类特殊方法。 引用材料: - [^1]:构造器总是伴随着new操作一起调用,对象一建立,构造器就运行且只运行一次。一般方法可以被调用多次。 - [^2]:类方法(“+”方法)类调用方法,不依赖于任何对象的方法,类似于c语言的static关键字。 - [^4]:构造方法在实例化对象时被调用。 相关问题: 1. Java中构造器和静态工厂方法的区别是什么? 2. 为什么构造器不能有返回值类型? 3. 如何通过反射调用构造器创建对象? </think>### 构造器属于类方法还是实例方法构造器(Constructor)**本质上属于类的特殊方法,既不是类方法(静态方法)也不是实例方法**。其特殊性体现在以下三个方面: #### 一、身份特殊性 1. **独立于类方法和实例方法** 根据Java规范: - 类方法:用`static`修饰,通过类名直接调用(如`Math.abs()`)[^2][^4] - 实例方法:依赖对象实例,通过对象调用(如`list.add()`)[^2][^4] - 构造器:无返回值声明,与类同名,只能通过`new`触发[^1][^3][^4] 2. **字节码验证** 在编译后的字节码中,构造器被标记为`<init>`方法,而类方法是`static`前缀,实例方法无特殊标记: ```java // 源代码 class Phone { Phone() {} // 构造器 -> 字节码: void <init>() static void f1() {} // 类方法 -> 字节码: static void f1() void f2() {} // 实例方法 -> 字节码: void f2() } ``` #### 二、调用机制特殊性 | 方法类型 | 调用方式 | 触发时机 | 调用次数限制 | |----------|---------------------------|----------------|--------------| | 类方法 | `类名.方法()` | 随时 | 无限制 | | 实例方法 | `对象.方法()` | 对象创建后 | 无限制 | | 构造器 | `new 类名()` | 对象创建时 | 仅一次[^1] | > **关键区别**:构造器无法通过常规方法调用语法执行(如`对象.构造器()`是非法的),只能通过`new`或反射机制激活[^1][^4]。 #### 三、功能特殊性 1. **内存分配责任** 构造器执行前,JVM已完成: - 堆内存分配 - 字段默认初始化(0/null/false) - 显式初始化(如`int x=5;`)[^1][^4] 2. **对象状态终结** 构造器负责: ```mermaid graph LR A[接收参数] --> B[验证参数有效性] B --> C[资源初始化] C --> D[建立对象完整状态] ``` 例如数据库连接的建立必须在构造器内完成[^3][^4]。 #### 四、设计原理验证 1. **继承规则** 构造器不可继承(子类必须通过`super()`调用父类构造器),而类方法和实例方法可被继承[^2][^3]。 2. **多态排除** 构造器不支持重写(override),这与实例方法的多态性本质不同[^1][^4]。 ### 结论 构造器是**独立于类方法和实例方法之外的第三种方法类型**,其核心特征: 1. **专属触发**:仅通过`new`或反射激活 2. **生命周期绑定**:仅在对象创建时执行一次 3. **内存管理角色**:完成对象从半初始化到可用状态的转换[^1][^3][^4]
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值