Разработчики рекомендуют определять имя пакета явно. Например, так:
package org //..
Хотя это и необязательно, но для удобства чтения, навигации по коду лучше сделать так, чтобы имя пакета и фактическое местоположения кода совпадали.
Всё нужно проверять на практике! Установили пакет - меняйте настройки параметров запуска программы - иначе программа не будет работать.
При запуске программы значение пакета устанавливается org.OrgPackage - программа не работает. Нужно менять значение пакета на org.HelloKt. Тогда программа опять запускается.
Примеры:
//это т.н. "точка входа" программы.
fun main (args: Array<String>):Unit {
}
fun summa1(a: Int, b: Int): Int {
return a +b;
}
fun summa2(a: Int, b: Int): Int {
return a +b
}
fun getB(b: Int): Int {
return b;
}
fun summa(b: Int): Int {
return b
}
fun summa_expression1 (a: Int, b: Int) = a + b;
fun summa_expression2 (a: Int, b: Int) = a + b
fun doSomothing() {
//Unit - тип данных функции, "маркер" того, что функция не возвращает данных
// ":Unit" его можно не писать в коде
}
// Определение переменных доступных только для чтения
val a: Int = 1;
val b = 1;
val c: Int;// если переменная не была определена в момент её объявления, её тип нужно задать явно c = 1;
val d = 45;
//Хотя символ ";" можно не указывать, но я думаю, что он всё же важен для удобства чтения кода на Java.
//Определение изменяемых переменных
var x = 5; // по умолчанию переменной "x" присваивается тип "Int"
fun main (args: Array<String>):Unit {
var x = 2;
//Как утверждает документация "строки могут содержать выражения" - т.е. код программы, которые может быть выполнен
//и помещён в строку.
//Любое выражение строкового шаблона начинается с символа $
//Если необходимо поместить код в стоковый шаблон, то он должен быть обрамлён символами "{" и "}".
println("$x +$x = ${x + x}");
println("${2+2}");
// Конечно возникает вопрос, а как использовать символ "$", если такая необходимость появляется
// Разработчики языка предлагают следующее решение
val price = "{'$'}99.9";
println(price);
Посмотреть, как работает строковый шаблон в Kotlin можно
(методом "копирование-вставкой") запустив код в настроенной среде разработки или на сайте.
Меня немного удивил то факт, что if в Kotlin имеет свой особый смысл. Это выражение, которое возвращает данные. В терминах Java - это метод, которые возвращает логическое значение.
Видимо поэтому если в коде программы значение if-выражения присваивается переменной или является чему-либо ещё оно обязательно должно иметь else-блок кода.
Примеры:
var result=-1;
var value1 = 1;
var value2 = 2;
if(value1 < value2)
result = value2;
println(result);
if(value1 < value2){
result = value2;
}
println(result);
//Использование альтернативного блока "else"
// Блок "else" не является обязательной частью. Его может не быть. Ошибки компиляции не будет.
if(value1 > value2){
result = value1;
} else{
result = value2;
}
result = if(value1 > value2) {
println("Выбрано значение $value1");
value1
}else
{
println("Выбрано значение $value2");
value2
}
println(result);
Коротко и ясно. Для тех кто волею судьбы знаком с языком программирования Perl. Думаю, улыбнутся про себе.
Как-будто программируешь на Perl. :-)
Наверное, возможность контроля, отслеживания нулевых значений на уровне языка программирования является одной из важных и полезных отличительных черт языка программирования Kotlin. Для этой цели введен символ обозначающий, что переменная, определение которой стоит перед данным символом может принимать null-значения. А отсутствие такого символа означает, что переменная не может содержать в себе null-значения.
"?" - специальный символ, определяющий, что переменная может содержать, т.е. ссылаться на null-значение.
Примеры:
В данном пример функция неявно возвращает null-значение. Т.е. если
fun main(args: Array){
if (args.size() < 2);
print("Ожидаем две переменные. Их нет. Попробуйте ещё раз!");
return
}
Возможно, это пример не очень удачный, т.к. функция main - является специальной в языке программирования.
Делаем логический вывод. Можно считать, что если у метода не указан тип возвращаемого значения - данная функция возвращает null неявным образом.
Приведём пример ошибки компиляции
var variable:String = "stirng value";
variable = null;
println(variable);
//Ошибка компиляции
Теперь посмотрим работу символа "?" коде программы:
var variable1: String? = "какое-то строковое значения";
variable1 = null;
println(variable1);
--------------------------
null
Теперь, если мы оставим код даже в таком виде:
var variable1: String? = "какое-то строковое значения";
variable1 = "новое значение переменной";
println(variable1);
и поместим его в тело метода main при компиляции программы вы обнаружите ошибку. Интересно, что вы увидите. Попробуйте!
Такой код не работает. А вот такой
var variable1: String? = "какое-то строковое значения";
variable1 = variable1!!.toUpperCase();
println(variable1);
"!!." - уловка, которой разработчики компилятора предлагаю воспользоваться, когда создателю программ на Kotlin очень будет нужно вызвать метод объекта переменной, которая может принимать null-значение.
var variable1: String? = "какое-то строковое значения";
variable1!! = "";
println(variable1);
Попытки подставить последовательность символов ".!!"
var variable1: String? = "какое-то строковое значения";
//variable1.!! = "";
//.!!variable1.!! = "";
//variable1.!! = .!!"";
//variable1.!! = .""!!;
//variable1.!! = "".!!;
println(variable1);
Приведут к красноречивым ошибкам компиляции.
Оператор is соответствие типа данных переменной какому-либо другому типу данных (классу, интерфейсу...чему-либо ещё). Благодаря использованию этого оператора появляется возможность сократить количество проверок, сравнении и, как следствие, приведению к нужному типу данных. Все эти проверки делает Kotlin за программиста.
Пример:
//Пример вызова NumberFormatExeption
/**Any - это тип данных эквивалентный Object, Int? - возвращаемый тип данных Int. Также сообщается, что возможно, что метод возвратит значение null. */
fun getStringValueAsInt(obj: Any) : Int? {
if(obj is String){
return obj.toInt();
}
return null;
}
fun main (args: Array<String>):Unit {
var obj:Any = "string";
var variable1: Int? = getStringValueAsInt(obj);
println(variable1);
}
А это рабочий код:
package org
/**Any - это тип данных эквивалентный Object, Int? - возвращаемый тип данных Int. Также сообщается, что возможно, что метод возвратит значение null. */
fun getStringValueAsInt(obj: Any) : Int? {
if(obj is String){
return obj.toInt();
}
return null;
}
fun main (args: Array<String>):Unit {
var obj:Any = Integer.valueOf("1").toString();
var variable1: Int? = getStringValueAsInt(obj);
println(variable1);
}
Тут есть над чем подумать, посмотреть в исходники, посмотреть в работе различные варианты типов данных. Очень интересные выводы. Без смеси Java + Kotlin такого рода проверки, приведение типа не сделают код безопасным. is, конечно, хорошее решение, но его зачастую не хватает. Если я хочу конвертировать строковое значение в числовое, то мне хорошо бы знать что это возможно заранее, а не с мощью NumberFormatExeption. Для такие целей методы класса Integer как раз будут полезны.
А вот ещё один пример приведения типа. В среде разработки он работает, а вот на сайте нет (Exception in thread "main" java.security.AccessControlException: access denied ("java.util.PropertyPermission" "1" "read")).
package org
/**Any - это тип данных эквивалентный Object, Int? - возвращаемый тип данных Int. Также сообщается, что возможно, что метод возвратит значение null. */
fun getStringValueAsInt(obj: Any) : Int? {
if(obj is String){
return Integer.getInteger(obj);
}
return null;
}
fun main (args: Array<String>):Unit {
var obj:Any = "1";
var variable1: Int? = getStringValueAsInt(obj);
println(variable1);
}
fun main(args:Array<String>){
for(arg in args) {
print(arg);
}
println();
for(i in args.indices) {
print(args[i]);
}
}
Протестировать данный код удобнее на сайте.
var i = 0;
while(i < args.size){
print(args[i++]);
}
fun main (args: Array<String>):Unit {
val y = "текст";
do{
val y = null;
}
while (y != null) // y is visible here!
}
Выражение when - это универсальная замена оператора swich. Данное выражение имеет свой особый синтаксис:
fun cases(obj: Any) {
when (obj) {
1 -> println("One value");
"Hello" -> println("World");
is Long -> println("Long type value");
!is String -> println("It is not a string value");
else -> println("Unknown value");
}
}
fun main (args: Array<String>):Unit {
var any = cases(1);
println(any);
any = cases("Hello");
println(any);
any = cases(Long.MAX_VALUE);
println(any);
any = cases(Int.MAX_VALUE);
println(any);
any = cases("Hello, Kotlin");
println(any);
}
Вот ещё один пример:
fun cases(obj: Any) {
when (obj) {
0, 1,"Hello", is Long -> println("Ура!");
else -> println("otherwise");
}
}
fun main (args: Array<String>):Unit {
cases(Long.MAX_VALUE);
}
Проверка вхождения значения в диапазон выглядит так:
fun main (args: Array<String>):Unit {
var y = 10;
var x = 10-1;
if (x in 1..y-1){
println("OK");
}else{
println("No");
}
}
Может быть я такой один не сообразительный, но всё-так мне не было не сразу понятно куда, к чему относится "-1". Запустив код и меня значения "x" мне стало всё понятно - "-1" относится к значению "y". Мне, как программисту Java, всё-таки более понятно вот такое решение:
fun main (args: Array<String>):Unit {
var y = 10;
var x = 10-1;
if (x in 1..(y-1)){
println("OK");
}else{
println("No");
}
}
Да, в нём чуть больше символов, но зато всё понятно.
Если мне нужно проверить действительно ли значение "x" не входит в диапазон, используется уже знакомый из Java оператор "!" (не)
fun main (args: Array<String>):Unit {
var y = 10;
var x = 10-1;
if (x !in 1..(y-1)){
print("OK");
}else{
print("No");
}
}
Перебирать значения диапазона можно вот так:
fun main (args: Array<String>):Unit {
for (x in 1..5){
print("$x ");
}
}
У каждая коллекция по-своему уникальна. Но всё-таки у коллекций есть общие черты. Благодаря этому возможны какие вот конструкции:
...
names
.filter { it.startsWith("A") }
.sortedBy { it }
.map { it.toUpperCase() }
.forEach { print(it) }