Отправляйтесь в путешествие в 1984 году. Apple выпустит Macintosh , « Финальная битва » вот-вот начнется в V, и Шотландия выиграет Five Nations, завершив в этом турнире турнир. Прямо в разгар забастовки шахтеров в Великобритании английская поп-группа Sade выпустила броский номер: Smooth Operator . Это был успех на графике в Великобритании и США (не говоря уже о немецком, голландском и австрийском графиках). Мало что знал Сэйд, что спустя десятилетия язык программирования Groovy будет содержать несколько гладких операторов, которые выходят за рамки стандартного набора операторов Java. Теперь мы оставим сравнения 1980-х годов и обсудим некоторые из гладких операторов в Groovy в этом сообщении в блоге.
Элвис
Оператор Элвиса (так назван в честь прически определенного человека) является сокращенной версией троичного оператора. Это очень удобно для нулевой проверки. И помните, хотя можно утверждать, что обработка нулей — плохая практика кодирования, потому что лучше не иметь нулей в вашем коде, многие API в кодовой базе неизбежно будут возвращать нули, и в реальном мире, где вы хотите добавить некоторую надежность и защитное кодирование для обеспечения бесперебойной работы, такого рода вещи могут быть полезны.
Теперь вот как это работает. Если выражение слева от оператора Элвиса оценивается как ложное ( помните, что в Groovy есть несколько вещей, таких как нуль, например, пустая строка, которую можно принудительно указать как ложное) , результатом выражения будет то, что включено право.
1
|
String country = country.name ?: "Unknown country" |
Итак, в приведенном выше примере, если country.name имеет значение null или просто «поскольку оба значения в Groovy имеют значение false, страна будет назначена как« Неизвестная страна ». Если country.name не было ложным, стране было бы просто присвоено это значение.
Null-Safe разыменование (также называемое оператором безопасной навигации)
Это особенно полезно, чтобы избежать исключений нулевого указателя в цепочечном выражении. Например,
1
|
String location = map.getLocation().getXandYCoordinates(); |
может привести к исключению нулевого указателя. Но используя оператор безопасной навигации, если либо map, либо результат map.getLocation () равны нулю
1
|
String location = map?.getLocation()?.getXandYCoordinates(); |
местоположение будет просто установлено как ноль. Таким образом, исключение нулевого указателя не выдается.
Распространение
Оператор Spread полезен при выполнении метода для элементов коллекции и получении результата. В этом примере я анализирую несколько строк в массивах, а затем запускаю замыкание на каждом из массивов, чтобы получить все первые элементы.
1
2
3
|
def names = [ "john magoo" , "peter murphy" ] def namesAsArrays = names*.split( " " ) namesAsArrays.each(){print it[ 0 ]} |
Теперь запомните, что оператор Spread может использоваться только для методов и элементов. Например, он не может выполнить закрытие. Но мы можем использовать возможности метапрограммирования Groovy для создания метода, а затем использовать оператор распространения для его вызова. Предположим, у нас был список чисел, которые мы тоже хотели добавить к 50, а затем умножить ответ на 6, что мы могли бы сделать:
1
2
3
|
def numbers = [ 43 , 4 ] java.lang.Integer.metaClass.remixIt = {(delegate + 50 ) * 6 } numbers*.remixIt() |
Оператор космического корабля
Это происходит от языка программирования Perl и называется так, как вы уже догадались, <=> выглядит как космический корабль! Итак, как это работает? Ну, это так. Выражение слева и справа от оператора космического корабля оценивается. -1 будет возвращено, если операнд слева меньше, 0, если левый и правый равны, и 1, если левый больше. Его сила должна стать более очевидной на примере.
Скажем, у нас есть класс для представления разработчиков программного обеспечения.
01
02
03
04
05
06
07
08
09
10
11
|
class SoftwareEngineer { String name int age String toString() { "($name,$age)" } } def engineers = [ new SoftwareEngineer(name: "Martin Fowler" , age: 50 ), new SoftwareEngineer(name: "Roy Fielding" , age: 48 ), new SoftwareEngineer(name: "James Gosling" , age: 58 ) ] |
Теперь мы можем легко отсортировать по возрасту
1
|
engineers.sort{it.age} |
Но что будет, когда наш список инженеров будет расти и расти, и у нас будет несколько инженеров одного возраста? В этих сценариях было бы неплохо отсортировать по возрасту первое и назвать второе. Мы могли бы достичь этого, выполнив:
1
2
|
engineers.sort{a, b -> a.age <=> b.age ?: a.name <=> b.name |
Это выражение попытается отсортировать инженеров по возрасту в первую очередь. Если их возраст равен a.age <=>, то b.age вернет 0. В Groovy и в конструкции Elvis 0 означает ложь, и, следовательно, a.name <=> b.name будет оценено и использовано для определения Сортировать.
Доступ к полю
В Groovy при попытке доступа к полю Groovy вызовет соответствующий метод доступа. Оператор доступа к полю — это механизм, заставляющий Groovy использовать доступ к полю.
1
2
3
4
5
6
7
8
|
class RugbyPlayer { String name String getName() {name ?: "No name" } } assert "Tony" == new RugbyPlayer(name: "Tony" ).name assert "No name" == new RugbyPlayer().name assert null == new RugbyPlayer(). @name |
Справочник по методам
Оператор Method Reference позволяет вам рассматривать ссылку на метод как замыкание.
1
2
3
4
5
6
7
8
|
class MyClass { void myMethod() { println "1" } void myMethod(String s) { println "2" } } def methodRef = new MyClass().& "myMethod" methodRef() // outputs 1 methodRef( 'x' ) // outputs 2 |
. & Создает экземпляр org.codehaus.groovy.runtime.MethodClosure. Это может быть присвоено переменной и впоследствии вызвано, как показано.
Поздравляю всех вас с Новым Годом и, надеюсь, еще немного блогов в 2014 году.