Есть ли способ поменять местами два разных объекта в Swift

Мне интересно, есть ли способ быстро поменять местами два разных объекта.

вот мой тест:

func swapXY<T>(inout first: T,intout second: T)
{
    (first ,second  ) = ( second,  first)
}

скажем, я хочу, чтобы два параметра были T, Y соответственно. Как это можно сделать?

Спасибо


person iShaalan    schedule 10.11.2015    source источник
comment
То, что вы хотите сделать, не имеет смысла. Даже если бы вы могли заставить объект Crocodile ссылаться на объект Trampoline, это может привести только к слезам.   -  person Crowman    schedule 11.11.2015
comment
@PaulGriffiths на самом деле я хочу поменять местами объект вместе с его типами, поэтому после замены (первый будет иметь тип Y)   -  person iShaalan    schedule 11.11.2015
comment
Опять же, это не имеет смысла. Какую проблему вы пытаетесь решить этим?   -  person Crowman    schedule 11.11.2015
comment
@PaulGriffiths Я не сталкиваюсь с проблемой, которую нужно решить, просто спрашиваю, почему я не могу выполнить такую ​​​​общую функцию. Это может быть полезно для кого-то рано или поздно.   -  person iShaalan    schedule 11.11.2015
comment
Вы не можете этого сделать, потому что ни одна функция не может вернуться назад и переписать код в вызывающей функции, чтобы ваши переменные ссылались на разные типы. Замена типов просто не имеет смысла в языке со статической типизацией, за исключением приведения типов, имеющих общий супертип. Лучшее, что вы можете сделать, это что-то с AnyObject, что почти наверняка не является правильным решением, и для которого ваша исходная функция подкачки в любом случае будет работать, поскольку задействован только один тип.   -  person Crowman    schedule 11.11.2015
comment
@PaulGriffiths, это хорошее объяснение, поэтому R U говорит, что основная проблема здесь заключается в том, что переменная не может изменить свой тип после инициализации?   -  person iShaalan    schedule 11.11.2015
comment
Это не проблема, это конструктивная особенность языка. Тип переменной определяется при ее объявлении, поэтому он устанавливается еще до ее инициализации, несмотря на тот факт, что компилятор Swift может вывести тип из значения, которое вы используете для его инициализации, если вы делаете это в момент объявления .   -  person Crowman    schedule 11.11.2015
comment
@PaulGriffiths, спасибо, я приму комбинацию ваших комментариев в качестве ответа позже сегодня, если никто не опровергнет это.   -  person iShaalan    schedule 11.11.2015


Ответы (4)


Да, вы можете поменять местами два элемента, и эта функция уже включена в стандартную библиотеку.

swap(_:_:)

Exchange the values of a and b.
Declaration

func swap<T>(inout _ a: T, inout _ b: T)

Справочник по функциям стандартной библиотеки Swift

Однако, если они не одного типа, то нет, вы не можете поменять местами два предмета разных типов.

Свифт 3

func swap<swapType>( _ a: inout swapType, _ b: inout swapType) {
  (a, b) = (b, a)
}
person Mr Beardsley    schedule 10.11.2015

Что вы можете сделать, так это гораздо более конкретную замену классов, наследуемых от общего предка:

class Animal {}
class Dog: Animal {}
class Cat: Animal {}

// Note that cat and dog are both variables of type `Animal`, 
// even though their types are different subclasses of `Animal`.
var cat: Animal = Cat()
var dog: Animal = Dog()

print("cat: \(cat)")
print("dog: \(dog)")

swap(&dog, &cat) // use the standard Swift swap function.

print("After swap:")
print("cat: \(cat)")
print("dog: \(dog)")

Приведенный выше код работает, потому что cat и dog оба являются "is-a" Animal как до, так и после замены. Однако замена объектов несвязанных типов в Swift невозможна, да и смысла в этом нет:

var dog = Dog() // dog is of type Dog, NOT Animal
var cat = Cat() // cat is of type Cat, NOT Animal
swap(&cat, &dog) // Compile error!

Этот код не будет компилироваться, потому что переменная типа Dog не может содержать значение типа Cat в Swift или любом другом строго типизированном языке.

person TotoroTotoro    schedule 11.11.2015

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

import Foundation

let a: (Int, String) = (1,"alfa")
let b: (Bool, NSDate) = (true, NSDate())

func foo<A,B>(t: (A,B))->(B,A) {
    return (t.1,t.0)
}

print(a, foo(a))    // (1, "alfa") ("alfa", 1)
print(b, foo(b))    // (true, 2015-11-22 21:50:21 +0000) (2015-11-22 21:50:21 +0000, true)
person user3441734    schedule 22.11.2015

person    schedule
comment
Пожалуйста, не публикуйте только код в качестве ответа, но также объясните, что делает ваш код и как он решает проблему вопроса. Ответы с объяснением, как правило, более качественные и с большей вероятностью привлекут положительные голоса. - person Mark Rotteveel; 27.04.2020