Поддерживает ли Swift преобразование пользовательских типов в кортежи? - PullRequest
0 голосов
/ 18 июня 2020

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

Возьмите этот класс ...

public class Person {

    public string FirstName { get; set; }
    public string LastName  { get; set; }

    public Person(string firstName, string lastName){
        FirstName = firstName;
        LastName  = lastName;
    }
}

Если вы добавите к его определению настраиваемый деконструктор, например ...

public class Person {

    ...

    public void Deconstruct(out string firstName, out string lastName){
        firstName = FirstName;
        lastName  = LastName;
    }
}

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

var p = Person("John", "Smith");

var (firstName, lastName) = p;

log(firstName); // Prints 'John'

Практически везде, где используется двухстрочный кортеж, теперь можно напрямую принимать объект Person, и деконструктор будет работать с помощью своего c magi, чтобы заполнить его значения. Он может даже делать выводы о типах, как это сделано выше.

Так поддерживает ли Swift деконструкторы для настраиваемых типов? Если нет, есть ли что-нибудь подобное?

1 Ответ

0 голосов
/ 18 июня 2020

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

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

One Swift -подобный способ сделать это - использовать протокол, который объявляет представление кортежа, и иметь любой объект, с которым вы хотите работать, в соответствии с протоколом. Вероятно, для описания требуется почти столько же слов, сколько для простого кодирования. :)

Вот пример протокола:

protocol TwoString {
    var tupl: (String, String) { get }
}

Вот простой класс, который принял протокол для возврата имени и фамилии:

class Name: TwoString {
    var first: String = ""
    var last: String = ""

    init(first: String, last: String) { self.first = first; self.last = last }

    var tupl: (String, String) {
        get {
            return (self.first, self.last)
        }
    }
}

Другой класс может принять протокол и использовать другую пару полей для кортежа, например

class Taxonomy: TwoString {
    var genus: String = ""
    var species: String = ""

    init(genus: String, species: String) { self.genus = genus; self.species = species }

    var tupl: (String, String) {
        get {
            return (self.genus, self.species)
        }
    }
}

Теперь у вас могут быть методы, которые принимают тип протокола TwoString , ничего не зная о базовом классе, за исключением того, что он может предоставлять двухстрочное представление самого себя.

Если вы хотите преобразовать объекты, которые вы изначально не определяли, для поддержки протокола, вы можете использовать расширение Swift, которое объявляет и реализует протокол на существующий класс:

extension Data: TwoString {
    var tupl: (String, String) {
        get {
            return (String(describing:self.count), self.base64EncodedString()) 
        }
    }
}

Теперь такой метод, как fun c handleTwoString (_ item: TwoString ), может принимать объект Name, Taxonomy или Data и получать двухстрочный кортеж, ничего не зная о базовом объекте.

Или, если вы хотите работать с API, которые принимают кортеж с двумя элементами, вы всегда можете просто явно передать член tupl:

SomeAPI.handleStringTuple(myName.tupl)
SomeAPI.handleStringTuple(taxonomy.tupl)
SomeAPI.handleStringTuple(someData.tupl)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...