我是Objective CI的新手我正在尝试一些示例程序。我无法理解自我和超级方法如何在目标C中工作。在下面的pgm中,CashTransaction.m [super trackSpending:amount]被调用并且在CreditCardTransaction中。 m [self trackSpending:amount]被调用。我找不到self和super.super之间的区别用于调用基类重写方法。而self用于调用子类重写方法。这就是我的理解。请如果我错了,请纠正我。谢谢你。
#import <Foundation/Foundation.h>
#import "BudgetObject.h"
#import "Transaction.h"
#import "CashTransaction.h"
#import "CreditCardTransaction.h"
int main (int argc, const char * argv[]) {
//!---Creating An Object And Allocating It With Values---
Budget* budget = [Budget new];
[budget createBudget:1000.00 withExchangeRate:1.2500];
//!---Declaring And Adding Elements To An Array---
NSMutableArray* transactions = [[NSMutableArray alloc] initWithCapacity:10];
Transaction* aTransaction;
aTransaction = [Transaction new];
[transactions addObject:aTransaction];
//!---Calculating The No Of Elements In An Array---
int k;
k=[transactions count];
NSLog(@"The count value is:%d",k);
//!---Selecting According To The Type Of Transaction---
for(Transaction *iTransaction in transactions){
switch ([aTransaction returnType]) {
case cash:
[budget spendDollars:[iTransaction returnAmount]];
break;
case credit:
[budget changeForeignCurrency:[iTransaction returnAmount]];
break;
default:
break;
}
}
Budget* europeBudget = [Budget new];
[europeBudget createBudget:1000.00 withExchangeRate:1.2500];
Budget* englandBudget = [Budget new];
[englandBudget createBudget:2000.00 withExchangeRate:1.5000];
NSMutableArray* transactions = [[NSMutableArray alloc] initWithCapacity:10];
Transaction* aTransaction;
for(int n=1;n<2;n++){
aTransaction = [CashTransaction new];
[aTransaction createTransaction:n*100 forBudget:europeBudget];
[transactions addObject:aTransaction];
aTransaction = [CashTransaction new];
[aTransaction createTransaction:n*100 forBudget:englandBudget];
[transactions addObject:aTransaction];
}
int n=1;
while (n<4) {
aTransaction = [CreditCardTransaction new];
[aTransaction createTransaction:n*100 forBudget:europeBudget];
[transactions addObject:aTransaction];
aTransaction = [CreditCardTransaction new];
[aTransaction createTransaction:n*100 forBudget:englandBudget];
[transactions addObject:aTransaction];
n++;
}
for(Transaction* aTransaction in transactions){
[aTransaction spend];
}
return 0;
}
#import <Cocoa/Cocoa.h>
@interface Budget : NSObject {
float exchangeRate;
double budget;
double exchangeTransaction;
}
- (void) createBudget: (double) aBudget withExchangeRate: (float) anExchangeRate;
- (void) spendDollars: (double) dollars;
- (void) changeForeignCurrency: (double) foreignCurrency;
@end
#import "BudgetObject.h"
@implementation Budget
- (void) createBudget: (double) aBudget withExchangeRate: (float) anExchangeRate;
{
budget = aBudget;
exchangeRate = anExchangeRate;
}
- (void) spendDollars: (double) dollars
{
budget = budget - dollars;
NSLog(@"Converting %0.2f into U.S Foreign Currency leaves $%0.2f",dollars,budget);
}
- (void) changeForeignCurrency: (double) foreignCurrency
{
exchangeTransaction = foreignCurrency * exchangeRate;
budget = budget - exchangeTransaction;
NSLog(@"Charging %0.2f in Foreign Currency leaves $%0.2f",foreignCurrency,budget);
}
@end
#import <Cocoa/Cocoa.h>
#import "BudgetObject.h"
@class Budget;
@interface Transaction : NSObject {
Budget* budget;
double amount;
}
- (void) createTransaction: (double) theAmount forBudget: (Budget*) aBudget;
- (void) trackSpending: (double) theAmount;
- (void) spend;
@end
#import "Transaction.h"
#import "BudgetObject.h"
@implementation Transaction
- (void) createTransaction: (double) theAmount forBudget: (Budget*) anBudget {
budget = anBudget;
amount = theAmount;
}
- (void) spend {
}
-(void) trackSpending: (double) theAmount {
NSLog(@"You are about to spend another %0.2f",theAmount);
}
@end
#import <Cocoa/Cocoa.h>
#import "Transaction.h"
@interface CashTransaction : Transaction {
}
@end
#import "CashTransaction.h"
#import "BudgetObject.h"
@implementation CashTransaction
- (void) spend{
[super trackSpending:amount];
[budget spendDollars:amount];
}
@end
#import <Cocoa/Cocoa.h>
#import "Transaction.h"
@interface CreditCardTransaction : Transaction {
}
@end
#import "CreditCardTransaction.h"
#import "BudgetObject.h"
@implementation CreditCardTransaction
- (void) spend {
[self trackSpending:amount];
[budget changeForeignCurrency:amount];
}
@end
2011-04-15 11:24:46.112 Bud Obj1[1041:a0f] You are about to spend another 100.00
2011-04-15 11:24:46.114 Bud Obj1[1041:a0f] Converting 100.00 into U.S Foreign Currency leaves $900.00
2011-04-15 11:24:46.115 Bud Obj1[1041:a0f] You are about to spend another 100.00
2011-04-15 11:24:46.115 Bud Obj1[1041:a0f] Converting 100.00 into U.S Foreign Currency leaves $1900.00
2011-04-15 11:24:46.116 Bud Obj1[1041:a0f] You are about to spend another 100.00
2011-04-15 11:24:46.119 Bud Obj1[1041:a0f] Charging 100.00 in Foreign Currency leaves $775.00
2011-04-15 11:24:46.120 Bud Obj1[1041:a0f] You are about to spend another 100.00
2011-04-15 11:24:46.120 Bud Obj1[1041:a0f] Charging 100.00 in Foreign Currency leaves $1750.00
2011-04-15 11:24:46.121 Bud Obj1[1041:a0f] You are about to spend another 200.00
2011-04-15 11:24:46.121 Bud Obj1[1041:a0f] Charging 200.00 in Foreign Currency leaves $525.00
2011-04-15 11:24:46.122 Bud Obj1[1041:a0f] You are about to spend another 200.00
2011-04-15 11:24:46.122 Bud Obj1[1041:a0f] Charging 200.00 in Foreign Currency leaves $1450.00
2011-04-15 11:24:46.123 Bud Obj1[1041:a0f] You are about to spend another 300.00
2011-04-15 11:24:46.123 Bud Obj1[1041:a0f] Charging 300.00 in Foreign Currency leaves $150.00
2011-04-15 11:24:46.124 Bud Obj1[1041:a0f] You are about to spend another 300.00
2011-04-15 11:24:46.125 Bud Obj1[1041:a0f] Charging 300.00 in Foreign Currency leaves $1000.00
答案 0 :(得分:14)
self
和super
的工作方式完全不同:self
表示运行时的调用对象,而super
表示类的超类方法定义是。在这两种情况下,它们都指定搜索方法应该从哪里开始,在self
的情况下,起始点是动态确定的,super
在编译时已知。
这是一个组成的例子:
@interface Grandparent : NSObject
- (void) One;
@end
@implementation Grandparent
- (void) One { NSLog(@"Grandparent One\n"); }
@end
@interface Parent : Grandparent
- (void) One;
- (void) Two;
@end
@implementation Parent
- (void) One { NSLog(@"Parent One\n"); }
- (void) Two
{
[self One]; // will call One based on the calling object
[super One]; // will call One based on the defining object - Parent in this case so will Grandparent's One
}
@end
@interface Child : Parent
- (void) One;
@end
@implementation Child
- (void) One { NSLog(@"Child One\n"); }
@end
@implementation FamilyAppDelegate
@synthesize window;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
Child *c = [Child new];
[c Two]; // will call the Two inherited from Parent
Parent *p = [Parent new];
[p Two]; // will call Parent's Two
}
@end
所以我们有三个班级; Grandparent
,Parent
和Child
;每个都有一个方法One
。课程Parent has a method
两个which calls
一个on
自and
超级。运行它会产生:
2011-04-15 22:49:05.006 Family[1993:a0f] Child One
2011-04-15 22:49:05.009 Family[1993:a0f] Grandparent One
2011-04-15 22:49:05.009 Family[1993:a0f] Parent One
2011-04-15 22:49:05.010 Family[1993:a0f] Grandparent One
对于Child
案例,调用[c Two]
会调用Two
从Child
继承的方法Parent
- 所以我们有继承。
现在,当Two
执行时,首先调用[self One]
,而self
是Child
的实例,其One
为Child
,One
'Parent
被执行 - 这是基于继承的多态性;在定义Two
的{{1}}时,Child
的未来存在未知,但在执行时,调用[self One]
可以调用Child
方法。
Two
中的下一个电话是[super One]
。现在已知这在定义时引用Grandparent
的{{1}}。
通常One
不引用超类中的方法(就像在本例中那样),但是对于方法,类型为超类的对象将调用,例如,它可能属于,super
。但是,无论调用什么方法都可以在编译时确定,因为任何类的祖先都是已知的。
调用Greatgrandparent
和[self *method*]
甚至可以调用相同的方法,在前一种情况下动态找到,并在后者中静态地知道。
希望您现在可以将继承[super *method*]
和self
应用于您的示例。
答案 1 :(得分:3)
self指的是在Objective-C编程中接收消息的对象。
在self上调用方法以通常的方式搜索方法的方法实现,从接收对象类的dispatch表开始。
示例:[self startThread]; self.hostReach = YES; BOOL值= self.hostReach;
1.self也是一个变量名,可以以多种方式使用,甚至可以分配一个新值。 2.在实例方法中,self指实例;但是在类方法中,self指的是类对象。
super是一个标志,告诉编译器在一个非常不同的地方搜索方法实现。它从类的超类开始,定义超出现的方法。
在super收到消息的任何地方,编译器将另一个消息传递例程替换为objc_msgSend函数。替换例程直接查看定义类的超类 - 即,将消息发送到超级而不是接收消息的对象的类的超类。超级允许方法实现的消息分发不止一堂课。
对于某些任务,继承层次结构中的每个类都可以实现一个方法,该方法执行部分工作并将消息传递给super以用于其余任务。初始化新分配的实例的init方法设计为这样工作。每个init方法都负责初始化其类中定义的实例变量。但在这样做之前,它会向super发送一条初始化消息,以使其继承的类初始化其实例变量。每个版本的init都遵循此过程,因此类按继承顺序初始化它们的实例变量。
答案 2 :(得分:1)
Super唤起了覆盖的方法。事实上,你的超级方法是空的。
如果我理解你的想法是正确的,那么你想创建CashTransactions和CCTransactions,并使用Transaction类与他们交谈。这样每次调用Transaction花费方法都会触发正确的子方法。那就是多态性。你只需要在运行时处理母类。孩子不需要超级,除非你留下所有孩子的共同代码。