2016-11-28 10 views
2

Objective-C имеет своеобразную, но очень полезную возможность сделать инициализатор возвратом другого экземпляра, чем тот, на который вызывается инициализатор. Вы можете прочитать об этом here.Можете ли вы вернуть другой экземпляр из конструктора Swift?

Это замечательно для таких вещей, как кластер классов, но даже для простых вещей, таких как обеспечение того, чтобы конкретные экземпляры были возвращены на основе определенных условий (то есть при создании класса учетной записи с номером учетной записи всегда будет возвращен один и тот же экземпляр класса Account для это число.)

Однако в нашем приложении мы используем Swift, но на этом языке я не вижу таких положений. Что-то подобное существует?

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

let foo = OurClass() 

Мы хотим контролировать, какой экземпляр передается обратно к ним на основе некоторых внешних условий (опущено для ясности здесь.)

Так же Swift есть любые такие механизмы?

+0

В настоящее время это невозможно в Swift, вы не можете создавать и возвращать экземпляр (подкласс) в методе init, если это то, что вы ищете. - Я * думаю *, который обсуждался в быстрой эволюции, но я не знаю, каков текущий статус. –

+0

Нет, это не то, что мы делаем. Мы просто возвращаем другой экземпляр класса (но того же типа), который вызван против init. Я думаю, что решение состоит в том, чтобы погрузиться в Objective-C, а затем вернуться обратно к быстрому. Дала бы нам то, что мы хотим, хотя и с любопытством в три левых к правильному. – MarqueIV

+1

Вот одна тема, о которой я думал: https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151214/003192.html. - В настоящее время вы не можете вернуть другой экземпляр (насколько мне известно), подкласс или нет. –

ответ

0

Хотя не так легко и чисто, как Objective-C, мы надеемся, вы должны быть в состоянии достичь своей цели, используя удобства инициализаторах или failable инициализаторах (или оба).

удобства инициализатор позволяет делегировать инициализацию другого инициализатора, по существу, дают вам контроль, как инициализируется объект:

class RecipeIngredient { 
    var quantity: Int 

    init(quantity: Int) { 
     self.quantity = quantity 
    } 
    convenience init() { 
     // You control how the properties are initialized here 
     if (/* Some external or internal condition */) { 
      self.init(quantity: 1) 
     } 
     else { 
      self.init(quantity: 2) 
     } 
    } 
} 

// The caller 
let mysteryFood = Food() 

failable инициализатор позволяет возвращать ноль в назначенном инициализаторе, если а условие не выполняется или при возникновении ошибки во время инициализации:

class Account { 
    var id: Int 

    // Failable initializers have '?' after init 
    init?(id: Int) { 
     // You control if the initialization succeeds or not 
     if (/* check your db if id is duplicate, for example */) { 
      return nil 
     } 
     // Succeeds 
     self.quantity = quantity 
    } 
} 

// The caller 
let account = Account(id: 5) 
if (account == nil) { 
    // It failed 
} 
else { 
    // It succeeded 
} 

в вашем случае, на основе ваших комментариев, это звучит, как вы хотели бы использовать failable initializer, который возвращает nil, если вызывающий пытается создать дубликат экземпляра.

Надеюсь, это соответствует строкам того, что вы ищете!

+3

Я знаю о неудачных инициализаторах и был действительно взволнован ими, когда я их впервые нашел ... до тех пор, пока я не понял, что единственное, что вы можете вернуть, это «ноль». Если они позволят вам вернуть новый/другой экземпляр, который будет наравне с решением ObjC и снова разрешить кластеры классов и более элегантную фабричную методологию класса без явного метода (поскольку вы просто используете инициализатор.) – MarqueIV

+1

Gotcha, это облом, надеюсь, скоро будет предложение о быстрой эволюции. – Midas

+2

Хотя это не отвечает на вопрос, оно предоставляет полезную информацию для людей, у которых может быть аналогичная проблема. Итак, поскольку у дубликата есть ответ, я отмечаю это здесь в хорошем S.O. гражданство, чтобы не иметь открытых вопросов. – MarqueIV

0

Насколько я могу судить, это невозможно для классов, но вы можете сделать это с помощью инициализаторов структуры (self = otherValue). Если возможно, класс может быть преобразован в структуру, которая, вероятно, будет способом.

Очевидная альтернатива (и, возможно, лучший дизайн) является заводским методом, и при работе с уже существующим API вы можете отказаться от этого инициализатора или сделать его ошибочным, указав вместо этого заводский метод. В противном случае есть несколько вариантов, которые приходят на ум.

  1. Скопируйте свойства экземпляра, который вы хотите вернуть в новый экземпляр, который вы создаете.
  2. Как и было предложено, выведите Objective-C для этого инициализатора.
  3. Используйте подкласс только для Swift и используйте использование конструктора.