在iOS中将对象转换为其子类



我有一个Person对象,它包含nameemailbirthdate等。

我还有一个Person的子类,叫做Member,它包含yearJoinedtitle等。

在我的代码中,如何获取现有的Person并将其转换为Member?例如:

Member *mem = self.person;

由于类不匹配,我收到了编译器错误。但是子类应该继承其父类的所有属性,所以我正在寻找一种方法,只说"这个Person对象现在应该是Member对象。">

这有道理吗?

一种方法是在Member类中声明initWithPerson类方法和memberFromPerson静态方法:

@interface Member : Person
{
NSString *title;
...
}
- (id)initWithPerson:(Person *)aPerson title:(NSString *)aTitle;
+ (Member *)memberFromPerson:(Person *)aPerson title:(NSString *)aTitle;
@end

在您的实施中:

@implementation Member
- (id)initWithPerson:(Person *)aPerson title:(NSString *)aTitle
{
if (self = [super initWithName:aPerson.name email:aPerson.email birthdate:aPerson.birthdate])
{
self.title = aTitle;
}
return self;
}
+ (Member *)memberFromPerson:(Person *)aPerson title:(NSString *)aTitle
{
return [[Member alloc] initWithPerson:aPerson title:aTitle];
}
@end

然后,当您想将Person实例转换为Member时,只需要调用:

Member *newMember = [Member memberFromPerson:myPerson title:@"New member!"];

当然,您可以根据是否需要title或year等其他变量来自定义所有这些(如果您正确初始化了所有内容,则可以创建不带任何其他参数的memberFromPerson:版本)。

面向对象的三个最重要的属性中有两个是多态性和继承性。

给定一个类a,继承允许您创建一个从a继承的类B,这意味着B继承了a中实现的所有数据成员和方法,此外,它还使您能够:

  • 重写A中定义的方法,专门化其行为
  • 添加新方法和数据成员

多态性允许在需要其超类A的地方使用继承的类B。

当你从A继承B时,B">知道"A是什么。事实并非如此,因为A不知道从它继承了多少类以及哪些类。因此,它不能表现得像是继承者的实例。

在您的案例中,Member是从Person继承而来的,因此Member可以用于任何需要Person实例的地方。但相反的情况是不可能的,除非您知道这在您的代码中发生:

Member *member = [[Member alloc] init];
Person *person = member; // This is ok, person is a superclass of member
...
...
Member *member2 = (Member *) person; // This, although stylistically questionable, is possible because you know person is an instance of Member

因此,当您100%确定它是Member的实例时,即使保持在Person类型的变量中,也可以从Person强制转换为Member

在以下情况下:

Person *person = [[Person alloc] init];
Member *member = (Member *) person;

编译器不会抱怨,但很可能会收到运行时异常。

为了明确这个概念,让我做一个简单的比较。MobilePhone是一个基类,SmartPhone从中继承。MobilePhone有一些功能(你可以拨打和接听电话、发送和接收短信等)。SmartPhone的行为就像MobilePhone,所以你可以像使用MobilePhone一样使用它,但你也可以做更多的事情,比如从AppStore安装应用程序(顺便提一下,"MobilePhone"是iPhone;-))、发送推文、阅读电子邮件、查看日历、天气等。所有这些都不能由MobilePhone来完成。

作为一种变通方法,@Romain提出的(好的)解决方案是一种广泛使用的常见模式。但您必须注意的是,它不是强制转换Member的新实例是用从Person复制的数据创建的。在某些情况下,了解这一点非常重要。

最新更新