2012-03-17 75 views
0

我想創建一個對象,但該類型取決於如果條件的結果:初始化對象,如果條件

if ([type isEqualToString:@"day"]) { 
    GraphDayView *graphv = [[GraphDayView alloc] initWithFrame:rect]; 
} else { 
    GraphMonthView *graphv = [[GraphMonthView alloc] initWithFrame:rect]; 
} 

的問題是,graphv超出範圍,所以我不能夠在if語句後使用它。 所以,我試圖將其聲明爲一個id:

id graphv; 

if ([type isEqualToString:@"day"]) { 
    graphv = [[GraphDayView alloc] initWithFrame:rect]; 
} else { 
    graphv = [[GraphMonthView alloc] initWithFrame:rect]; 
} 

但現在的問題是,該編譯器不知道什麼樣的對象grapv的是。所以:

graphv.backgroundColor = [UIColor whiteColor]; 

提供了一個錯誤。任何人都知道如何解決這個問題?

+1

通常你在這種情況下使用一個通用的基類,這是可能的嗎? – 2012-03-17 13:57:09

回答

2

如果他們共享相同的超類,那麼使用它來代替id。否則,創建兩個變量,並將它們設置爲nil:

GraphDayView *gdv = nil; 
GraphMonthView *gmv = nil; 

然後測試後的if語句,看看哪一個被初始化。

1

使GraphDayView和GraphMonthView都是GraphCalendarView的子類。然後使您的backgroundColor成爲GraphCalendarView的一個屬性。

(或者,如果你的兩個類都已經實現backgroundColor然後你回家免費的UI類的子類)。

聲明你的變量爲GraphCalendarView graphv;,然後像以前一樣繼續進行。如果你需要使用一個屬性/方法,這對你的兩個派生類中的一個或另一個來說是獨一無二的,那麼就先投射到那個類。

+0

Assumin都是UIView子類,那麼你可以簡單地定義對象作爲/ UIView的實例。這將爲backgroundColor做。正如Hot Licks所建議的,根據子類的其他方法,您可能想要在UIView和您的子類之間引入一個通用超類。 – 2012-03-17 14:16:18

+0

謝謝,這工作,很好的解決方案!一個問題,但。我在這兩個子類中都有一個名爲'setMeasurements'的方法。我應該將其聲明爲抽象方法還是最好做什麼? – joostevilghost 2012-03-17 14:17:31

+1

要麼使它們繼承自從'UIView'繼承的公共基類,例如'@interface GraphCalendarView:UIView'然後'@interface GraphMonthView:GraphCalendarView'和'@interface GraphDayView:GraphCalendarView'。或者如果他們沒有真正分享任何其他的共同性,並且你不想強加這種關係,你可以創建一個他們都遵守的協議,他們可以繼續從'UIView'繼承。 – 2012-03-17 14:30:23

0

試試這個,

id graphv; 

if ([type isEqualoString:@"day"]) { 
    (GraphDayView *)graphv = [[GraphDayView alloc] initWithFrame:rect]; 
} else { 
    (GraphMonthView*)graphv = [[GraphMonthView alloc] initWithFrame:rect]; 
} 
+0

這樣做可能會使代碼更平滑,但更容易出錯。但是,graphv仍然是id類型的對象,編譯器在訪問屬性或調用GraphDayView甚至UIView的方法時仍會引發警告。當使用ARC時,編譯器甚至會拋出錯誤並停止構建過程。 – 2012-03-17 14:46:02

0

很多的通用超建議被做了最適合liekly。

如果他們不是,那麼你可以使用typcasts。但是,類型轉換可能會導致像未知選擇符或bad_exec這樣的異常。如果您想要節省地使用typcast,那麼您應該始終檢查isKindOfClass或respondsToSelector。

樣本:

id someClassObject; //或任何其他常見的超類*代替id

如果([something is True]) someClassObject = [[AClass alloc] init]; //假設ARC。如果沒有,那麼你也可能想在這裏保留/ autorelease。 else someClassObject = [[AClass alloc] init];

... //一些代碼

如果([someClassObject isKindOfClass:[ACLASS類]]) [(ACLASS *)someClassObject methodOfAClass];如果([someClassObject isKindOfClass:[AClass class]]){ AClass * aClassTemp =(AClass *)someClassObject; [aClassTemp methodOfAClass]; aClassTemp。propertyOfAClass = someValue; }

如果([someClassObject respondsToSelector:@selector(methodOfBClass :)) [someClassObject perforformSelector:@selector(methodOfBClass :) withObject:的UIColor clearColor]];

注意:選擇器名稱後面的數字與方法的參數數量相關。對於每個可能的方法調用,您可能找不到適當的performSelector差異。特別是你可以只傳遞或返回對象的引用。

再次,他們兩個我只會建議如果共同的子類不適合你的情況。