2009-06-29 49 views
0

矩形和圓的常見超類是形狀。Objective-C子類initWithSuperClass

如果我初始化一些形狀,稍後將形狀轉換爲圓形並在形狀中保持相同屬性的好方法是什麼?我應該在看起來像這樣的子類中實現initWithShape嗎?

- (id) initWithShape:(Shape*)aShape { 
    self = (id) aShape; 

    // set circle or rectangle specific values 

    return self; 
} 

有沒有人有我可以看看的例子?

回答

1

創建後的對象除了釋放它並創建一個新對象(您可以在init方法中執行,實際上經常爲單例或類集羣完成)之外,您無法更改該對象,但是並不是你真正想要的。

給一個現有的Shape對象,有一些屬性,你唯一真正的選擇是根據形狀屬性創建一個新的對象。喜歡的東西:

在Shape.m:

- (id) initWithShape:(Shape*)aShape { 
    self = [super init]; 
    if (self != nil) { 
     // copy general properties 
     _x = aShape.x; 
     _y = aShape.y; 
     _color = [aShape.color copy]; 
    } 
    return self; 
} 

在Circle.m:

- (id) initWithShape:(Shape*)aShape { 
    self = [super initWithShale:aShape]; 
    if (self != nil) { 
     // base properties on the class of the shape 
     if ([aShape isKindOfClass:[Oval class]]) { 
      // average the short and long diameter to a radius 
      _radius = ([(Oval*)aShape shortDiameter] + [(Oval*)aShape longDiameter])/4; 
     } else { 
      // or use generic Shape methods 
      _radius = aShape.size/2; 
     } 
    } 
    return self; 
} 
+0

謝謝。這是我正在尋找的。在Shape.m中放入一個initWithShape使得在查看Circle.m時代碼清晰 – 2009-06-30 04:04:44

2

不要做你剛做的事情。想想,當你這樣做會發生什麼:

Shape *shape = ...; 
Rectangle *rect = [[Rectangle alloc] initWithShape:shape]; 

在第二線,Rectangle一個實例被分配。那麼,initWithShape的返回值只是shape,所以我們剛剛分配的新Rectangle已被泄漏!

轉換爲id也是不必要的 - 任何Objective-C對象都可以隱式轉換爲id

我不完全清楚你想要做什麼。也許如果你澄清了你的問題,我可以告訴你你應該做什麼。

0

如果你有一個形狀的參考,它可能是一個矩形或五角星形或任何,你想'轉換'爲一個圓圈(我想你的意思是一個圓,具有相同的邊界框?),你必須創建一個新對象。創建對象後,你不能改變對象的類別(除非通過非常討厭的低級別黑客)。

所以是的,你可以在Circle類中創建一個-initWithShape:方法。但該方法看起來像一個普通的init方法,設置了新的Circle對象的實例變量('self')。它將訪問給定Shape的屬性,如其位置和大小,並相應地設置新對象。

0

爲什麼不實現你的形狀的方法可以從其他形狀的特性,而不是試圖取代完全是對象的實例。這可能更安全。

// for rectangle 
- (void) takePropertiesFrom:(Shape *) aShape 
{ 
    if ([aShape isKindOfClass:[Circle class]]) 
    { 
     float radius = [aShape radius]; 
     [self setWidth:radius * 2]; 
     [self setHeight:radius * 2]; 
    } 
    else 
    { 
     [self setWidth:[aShape width]]; 
     [self setHeight:[aShape height]]; 
    } 
} 

// for circle 
- (void) takePropertiesFrom:(Shape *) aShape 
{ 
    if ([aShape isKindOfClass:[Rectangle class]]) 
     [self setRadius:[aShape width]/2]; 
    else 
     [self setRadius:[aShape radius]]; 
} 

很明顯,你會想建立一個公共接口Shape暴露的形狀的基本屬性,如高度和寬度,然後你將不再需要硬編碼性能偷基於類類型。