2013-04-25 2 views
1

Привет всем, Я работал над некоторыми процедурами перечисления в Objective-C, которые выполняют интроспекцию объекта. В частности, я быстро перечисляю NSSet и удостоверяюсь, что объекты в нем принадлежат классу BBBallView (довольно неудачное имя, я согласен), прежде чем настраивать их свойства и/или вызывать их методы.Самоанализ Obj-C: как избежать кастинга все время?

Однако, чтобы сделать синтаксический анализатор и компилятор счастливым, я заканчиваю тем, что бросаю объект в его класс на каждой отдельной строке; кроме того, чтобы получить доступ к своим свойствам, листинг объекта должен быть в круглых скобках, иначе точечная нотация не будет работать. Это приводит к нескольким грязному коду:

for (id otherBall in self.gameField.subviews) { 
    if ([otherBall isKindOfClass:[BBBallView class]]) { 
     if (!((BBBallView *)otherBall).isEnlarged) { 
      CGRect otherFrame = ((BBBallView *)otherBall).frame; 
      /* ... */ 
     } 
    } 
} 

Есть ли способ, чтобы сказать что-то вроде компилятора «на данный момент я знаю, что otherBall является BBBallView, так что перестаньте говорить мне, что это не отвечает на эти селекторы и свойство «? Таким образом, можно просто написать:

for (id otherBall in self.gameField.subviews) { 
    if ([otherBall isKindOfClass:[BBBallView class]]) { 
     if (!otherBall.isEnlarged) { 
      CGRect otherFrame = otherBall.frame; 
      /* ... */ 
     } 
    } 
} 

и так далее.

Я пробовал otherBall = (BBBallView *)otherBall, но «быстрые переменные перечисления не могут быть изменены в ARC по умолчанию». Изменение переменной перечисления до __strong id исправляет ее, но не помогает в том, что любая последующая строка выдает ошибки, такие как «property isEnlarged не найден на объекте типа« const __strong id », поэтому я возвращаюсь к квадрату.

Я даже не уверен, почему именно это происходит: не должен ли компилятор оставаться в стороне, когда переменная имеет тип id? В любом случае, все испытания особенно беспорядочны в методах, которым необходимо выполнить несколько вычислений по свойствам объектов, так как они быстро становятся нечитаемыми со всеми этими круглыми скобками.

Есть ли способ обойти это?

Заранее благодарен!

+0

В целом, сложные рисунки с интроспекцией - это * запах кода *. Коллекции вообще не должны содержать гетерогенные типы. Кроме того, наличие абстрактного класса, который предоставляет базовые услуги с определенными подклассами, которые улучшают поведение, избегают много интроспекции. – bbum

ответ

4

Вы можете создать локальную температуру с правильным типом или просто не использовать точечную нотацию.

  1. локальной температура

    for (UIView *view in self.gameField.subviews) { 
        if ([view isKindOfClass:[BBBallView class]]) { 
        BBBallView *ballView = view; 
        if (!ballView.isEnlarged) { 
         CGRect otherFrame = ballView.frame; 
         /* ... */ 
        } 
        } 
    } 
    
  2. не использовать точечную нотацию

    for (id otherBall in self.gameField.subviews) { 
        if ([otherBall isKindOfClass:[BBBallView class]]) { 
        if (![otherBall isEnlarged]) { 
         CGRect otherFrame = [otherBall frame]; 
         /* ... */ 
        } 
        } 
    } 
    

Если я только делал пару вещей я бы соблазн не использовать точку нотации.Если стало неудобно читать и было много доступа, тогда я бы рассмотрел местную временную ситуацию

+1

Я просто хотел написать совершенно тот же ответ ... но вы ставите меня! +1 :) – HAS

+0

У вас есть точка (не каламбур!), Используя временную локальную переменную, вероятно, лучший способ для удобочитаемости. Я предпочел бы придерживаться точечной нотации, в основном для согласованности кода. Я понятия не имею, почему я не думал об этом, возможно, в моем сознании я думал, что растрачиваю память, но это просто еще один указатель, а не копия, поэтому локальная переменная! Простой и эффективный. Благодарю. :) – Jollino

1

Я думаю, вы боретесь, потому что логика кажется неуместной. Язык сражается с вами из-за структуры вашей программы, а не потому, что язык недостаточен.

Действительно ли подходит тип родительского типа? Или вы нарушаете Принцип замещения Лискова, набивая круглый объект квадратным типом?

Вы также можете узнать, действительно ли целесообразно исследовать внутренние элементы логики BBBallView снаружи? Можете ли вы переместить логику в соответствующий класс?

Смежные вопросы