Статьи

Swift для Java Guy: Часть 2 — Основы

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

В первую очередь; Что то же самое.

Оба языка являются ОО-языками, основанными на классической статической типизации, с единым наследованием и интерфейсами. Кроме того, Swift включает в себя обычный набор функций, которые имеет Java, в том числе:

  • Try-Catch style Обработка исключений
  • Синтаксис в стиле C
  • Дженерики
  • Функции первого класса и высшего порядка

Что отличается

Swift сильно отличается в ключевых областях, включая

  • Управление памятью на основе ссылок с использованием автоматического подсчета ссылок, а не сборщика мусора.
  • Классы Swift не наследуются от базового класса объектов.
  • Классы Swift не нужно объявлять в файле, который следует шаблону пространства имен и имени класса.
  • Все методы в Swift являются функциями, Void в Swift необходим для псевдонима типа пустого кортежа.
  • У Swift есть только три модификатора доступа, private и public, которые ведут себя аналогично Java-эквивалентам. Он также имеет internal который является Swifts эквивалентом доступа по умолчанию, однако Swift не имеет защищенного модификатора.
  • Интерфейс Swift (или протоколы, как они называются на языке Swift) не может иметь реализации по умолчанию (хотя вы можете добиться того же эффекта с помощью расширений).
  • Перечисления в Swift «разные». Лучший способ, который я могу описать, это то, что Swift Enum — это, по сути, набор с именем Tuples, которые сгруппированы в объявлении Enum, каждый из которых может объявить свою собственную структуру.

То, что есть у Swift, у Java нет.

Swift имеет ряд функций, которых нет в Java

  • Типы значений (структуры)
  • Кортеж
  • Типы расширения
  • Перегрузка оператора
  • Тип вывода
  • Уровень языка необязательные монады и строгая проверка нуля
  • свойства
  • деструкторы
  • Значения и переменные в отличие от просто переменных аля Scala
  • Вложенные функции (функции АКА внутри функций)
  • Сопоставление с образцом

Объявление вашего первого класса в Swift

Для этого примера я создаю простой класс «Animal» с единственным пустым методом makeSound

1
2
3
4
5
6
class Animal {
  func makeSound() -> Void {
    print("Roar!!")
  }
}
Animal().makeSound()

Несколько замечаний:

  • Методы Swift явно объявляются с ключевым словом func и имеют тип возврата после оператора «->», который является противоположным порядком подхода Java в терминах объявления.
  • Последняя строка создает новый экземпляр Animal и вызывает метод makeSound . Обратите внимание, что Animal также имеет неявный конструктор no-args constructor , также нет new ключевого слова.

Добавление собственности

Таким образом, очевидно, что не все животные ревут, чтобы исправить это, мы добавляем sound свойства в класс, добавляя следующее

1
2
3
4
5
6
7
8
9
class Animal {
  var sound:String = "Croak"
  func makeSound() -> Void {
    print(sound)
  }
}
let animal = Animal()
animal.sound = "Roar"
animal.makeSound()

По умолчанию все переменные (обозначаемые ключевым словом var ), объявленные как члены, являются свойствами. Что здесь не видно, так это то, что когда вы устанавливаете свойство звука, к нему фактически обращаются через методы доступа, которые создаются неявно. Еще один момент, о котором стоит упомянуть, это то, что переменная animal вообще не является переменной, а является константой, как указано ключевым словом let ключевое слово let является эквивалентом Swift ключевого слова val в Scala.

Конструкторы

В предыдущем примере я установил roar значение по умолчанию «Croak». Было бы лучше, если бы мы могли передать эту информацию через конструктор и сделать свойство звука неизменным, для этого мы изменим класс следующим образом:

01
02
03
04
05
06
07
08
09
10
11
class Animal {
  let  sound:String
  init(sound:String) {
    self.sound = sound
  }
  func makeSound() -> Void {
    print(sound)
  }
}
let animal = Animal(sound:"Roar")
animal.makeSound()

Конструкторы в Swift немного отличаются от Java с точки зрения синтаксиса тем, что они определены внутри блока, определенного с помощью ключевого слова init . Эти блоки могут принимать параметры так же, как в конструкторе Java. Я также изменил свойство звука с var на let , это означает, что свойство sound не может быть переназначено после его назначения. Здесь также стоит показать, что Swift требует от вас использования именованных параметров при вызове конструктора, это будет знакомо любому, кто когда-либо использовал Objective-C.

Добавление интерфейса (или протокола)

Поскольку Animals — не единственное, что создает звук, мы можем использовать эту функцию в протоколе под названием Audible который может быть реализован классом Animal .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
protocol Audible {
  func makeSound() -> Void
}
 
class Animal:Audible {
  let sound:String
  init(sound:String) {
    self.sound = sound
  }
  func makeSound() -> Void {
    print(sound)
  }
}
 
let audible:Audible  = Animal(sound:"Roar")
audible.makeSound()

Здесь я добавил протокол с методом makeSound, помимо ключевого слова protocol , это должно показаться знакомым большинству разработчиков Java. Единственное изменение в классе Animal заключается в том, что он реализует Audible . Синтаксис для расширения и реализации — это синтаксис двоеточия, который работает так же, как C #. Я также явно напечатал свое слышимое значение, чтобы иметь тип Audible просто чтобы вызвать upcast.

Свойства по протоколам

Со свойствами собственности на протоколы. Для этого примера я создал другой протокол с именем Named который просто имеет свойство String; name

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
protocol Named {
   var name:String {get set}
}
protocol Audible {
   func makeSound() -> Void
}
 
class Animal: Audible, Named {
  let sound:String
  var name:String
  init(sound:String, name:String) {
    self.sound = sound
    self.name = name
  }
  func makeSound() -> Void {
    print(sound)
  }
}
let animal  = Animal(sound:"Roar", name:"Lion")
print(animal.name)
animal.makeSound()

В этом примере также показана изменчивость свойства name с использованием ключевых слов get и set . Интересно, что мне еще нужно определить фактическую переменную имени в классе Animal . Помня о том, что протокол определяет поведение, свойство в протоколе указывает только на то, как структурировано свойство, а не на то, как оно хранится, это является обязанностью реализующего класса.

наследование

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
class LivingOrganism:Named  {
   var name:String
   init(name:String) {
     self.name = name
   }
}
 
class Animal: LivingOrganism, Audible {
  let sound:String
  init(sound:String, name:String) {
    self.sound = sound
    super.init(name:name)
  }
  func makeSound() -> Void {
    print(sound)
  }
}

Снова обратите внимание на синтаксис наследования в стиле C #. Еще одна интересная вещь, которую стоит отметить, это использование ключевого слова super, которое в Java ведет себя как super. В этом случае я вызвал метод init суперкласса внутри Animal. Одно из отличий от Java заключается в том, что Swift требует, чтобы локальные переменные были инициализированы в первую очередь перед вызовом супер-конструктора, следовательно, вызов является последней строкой конструктора Animal. Это обратная сторона Java.

Итак, у нас есть базовый обзор построения классов в Swift. В следующей части мы рассмотрим некоторые дополнительные функции Swift, такие как проверка Tuples и Strict Null с дополнительными монадами.

Ссылка: Swift for Java Guy: Часть 2 — Основы нашего партнера JCG Джулиана Эксенбергера в блоге Dot Neverland .