(自分用メモ)そこそこ似てる上に同時に使うことが多くて混乱しますよね..
クラス
メンバ・メソッドを持たないクラスC0
メンバmを持つクラスC1
メンバm・メソッドfを持つクラスC2とそのインスタンス化
Kotlin
class C0
class C1(val m:Int)
class C2(val m:Int) {
fun f() = m
}
val c2 = C2(123)
println(c2.f())
TypeScript
class C0{}
class C1{
m: number
constructor(m: number) {this.m = m}
}
class C2{
m: number
constructor(m: number) {this.m = m}
f() { return this.m }
}
let c2=new C2(123)
console.log(c2.f())
Dart
//TODO
Getter/Setter
Kotlin
var io // 変数毎に定義可
get() = readln()
set(s) = println(s)
io = "Hello ${io}." // 標準入力内容を"Hello "に続けて標準出力する。
TypeScript
class StdIO {
get io(): string { return process.stdin.read() }
set io(o: string) { console.log(`Hello:${o}`) }
}
Dart
class Person {
late int _age;
int get age => _age;
set age(int old) => _age = old;
}
定数/変数
- 定数: ビルド時に値が決定される。定数のみ割り当て可
- イミュータブル: 実行時に1回だけオブジェクトを割り当て可
- ミュータブル: 実行時に1回以上オブジェクトを割り当て可
Kotlin
const val c=1; // 定数、ローカル宣言不可
val imu=c; // イミュータブル
var mu=imu; // ミュータブル
TypeScript
// 定数はない?
const imu=1 // イミュータブル
let mu1=imu // ミュータブル(ブロック内から参照可)
var mu2=imu // ミュータブル(関数内から参照可)
Dart
const c=1; // 定数
final imu=c; // イミュータブル
var mu=imu; // ミュータブル
データ型
nameとageを持つデータ型Personを定義/生成/参照
Kotlin
data class Person(val name:String="noname",val age:Int?,)
val user=Person("shokka",23)
println("${user.name} / $user")
TypeScript
type Person= { name: string, age:number, }
const user={name:"shokkaa",age:23,} as Person
console.log(`${user.name} / ${user}`)
Dart:機能なし(freezed等でヘルパコードを生成する必要あり)
Dart/person.dart
import 'package:freezed_annotation/freezed_annotation.dart';
part 'person.freezed.dart'; // freezedで生成
@freezed
class Person with _$Person {
factory Person({@Default('noname') String name, int? age}) = _Person;
factory DiscoveryResult.fromJson(Map<String,Object?> map)=> _$DiscoveryResultFromJson(map); // Mapからの変換
}
main() {
final user = Person(name: "shokkaa");
print('${user.name} / ${user.toString()}');
}
関数定義、関数型と関数リテラル
引数に文字列を与え数値を返す関数f1、
同関数リテラルを格納する変数f2、
Kotlin
fun f1(s:String):Int {return s.toInt()}
fun f1(s:String):Int = s.toInt() // 式表現
val f2:(String)->Int = {s:String->s.toInt()}
val f2 = {s:String->s.toInt()}
TypeScript
function f1(s:string):number {return parseInt(s)}
const f2:(s:string) => number = function(s:string){parseInt(s)}
const f2:(s:string) => number = (s:string)=>parseInt(s)
const f2 = (s:string)=>parseInt(s)
Dart
int f1(String s) {return int.parse(s);}
int f1(String s) => int.parse(s); // 式表現
int Function(String) f2 = (s) => int.parse(s);
final f2 = (String s) => int.parse(s);
拡張関数
クラス外で Objectに対する操作を定義する。
文字列の前後に括弧[]を付けて返す拡張関数bracketedと、実行例。
整数の配列の「1番目の要素+2番目の要素」を返す拡張関数add12()
Kotlin
fun String.bracketed()="[$this]"
println("aaa".bracketed()) // [aaa]
fun List<Int>.add12() = this[0]+this[1]
Typescript
declare global { // modlueを指定する場合は declare module "xxx"
interface String {bracketed(): string }
}
String.prototype.bracketed = function(){return `[${this}]`}
console.log("aaa".bracketed()) // [aaa]
interface Array<T> {add12(): T }
Array.prototype.add12 = function(){return this[0]+this[1]}
console.log([1,2,3].add12()) // 3
console.log(['1','2','3'].add12()) // 12 ... number[]だけに適用したいのに...
Dart
extension StringExt on String {
String bracketed() {return "[$this]";}
}
void main() {
print("aaa".bracketed());
}
// TODO
非同期関数
1秒待つ関数
Kotlin
suspend fun sleep1s() = delay(1000)
fun main() = runBlocking {
println("1秒寝る")
sleep1s()
println("起きた")
}
TypeScript
async function sleep1s() {
await new Promise(resolve => setTimeout(resolve, 1000))
}
async function test() {
console.log("1秒寝る")
await sleep1s()
console.log("起きた")
}
test()
Dart
TODO
非同期反復
Kotlin
// Flow
suspend fun Main(){
(1..3).asFlow().collect{
println(it)
sleep1s()
}
}
TypeScript
// ジェネレータ関数
function* gen() { for(const i of [1,2,3]) {yield i}}
async function test() {
for await (const i of gen()) {
console.log(i)
await sleep1s()
}
}
test()
Dart
TODO
Nullable変数定義/Null許容型
Kotlin
var v:Int? = null
TypeScript
let v: number| null = null
let v2: number | undefined // 未定義許容型
Dart
int? v = null;
int? v2; // =null 省略可。 https://dart-lang.github.io/linter/lints/avoid_init_to_null.html
リスト/マップの生成/変換と型
Kotlin
val v:List<Int> = listOf(1,2,3) // 要素数固定の配列を生成
val v2:List<Int> = listOf(0,*v,4) // スプレッド演算子を使用し先頭/末尾に追加 [0,1,2,3,4]
val m:Map<Int,Int> = listOf(1 to 1,2 to 4,3 to 9).toMap()
Typescript
const v=Array<number>(1,2,3) // 配列生成関数
const v=[1,2,3] // 配列リテラル
const v2=[0,...v,4] // スプレッド演算子を使用し先頭/末尾に追加 [0,1,2,3,4]
const m = new Map([[1, 1],[2, 4],[3, 9],]) // 要素数固定の配列を生成
const m = new Map([1,2,3].map((e)=>[e,e*e])) // 動的な配列を生成
Dart
const List<int> v = List.generate(3, (i)=>i*i);
const v = [1,2,3];
const v2=[0,...v,4] // スプレッド演算子を使用し先頭/末尾に追加 [0,1,2,3,4]
表: 主な型とリテラル
Kotlin | TypeScript | Dart | |
---|---|---|---|
整数 | - | - | const int i=1; //JS上では有効54bit |
32bit整数 | val i:Int=1 | - | - |
64bit整数 | val l:Long=1L | - | - |
8bit整数 | val by:Byte=1B | - | - |
符号なし8bit整数 | val uby:UInt=1UB | - | - |
実数(float) | val f:Float=1.2 | - | - |
実数(double) | val d:Double=1.2 | - | const double d=1.2; |
数値 | val n:Number=1.2 | const n:number=1.2 | const num n=1.2; |
文字 | val c:Char='c' |
- | - |
文字列 | val s:String="str" |
const s:string="str" | const String s = "str"; |
論理値 | val b:Boolean = false |
const n:boolean=false | const bool b=false; |
配列/List | val v:List<Int> =listOf(1,2,3) |
const v:number[] = Array<number>(1,2,3) |
List<int> v=<int>[1,2,3]; |
連想配列/Map | val m:Map<String,Int> = mapOf("a" to 1) |
const m:Map<string,number> = new Map([["a",1]]) |
Map<String,int> m = <String,int>{"a":1}; |
基底クラス | val a:Any=1 |
const a:Object=1 |
Object a=1; |
null許容 | val i:Int?=null |
const i:any|null=null |
int? i=null; |
型チェック | if(d is Map){} |
||
List/Map: 変換
Kotlin
Typescript
Dart
List: ソート
[4,3,5,2,1] => [1,2,3,4,5]
Kotlin
val s = listOf(4,3,5,2,1)
val r1 = s.sorted()
val r2 = s.sortedBy{it}
val r3 = s.sortedWith{a,b->a-b}
Dart
import 'package:collection/collection.dart';
final s = [4,3,5,2,1];
final r = list.sorted((a,b)=>a-b);
イテレーション: 階層をフラット化
[[0,1,2],[3,4]] => [0,1,2,3,4]
Kotlin
val v = listOf(listOf(0,1,2),listOf(3,4))
val r = v.flatMap{it} // ブロックの結果はリストであること
Typescript/ES2019
const v=[[0,1,2],[3,4]]
const r=v.flat() // [0,1,2,3,4]
// ネスト深度を指定できる。デフォルト1
const v=[[0,[1,2]],3,[4,[]]] // 参考:vの型はこう推論される.. (number | (number | number[])[])[]
const r=v.flat(2) // [0,1,2,3,4]
Dart
final v = [[0,1,2],[3,4]];
final r = v.expand((e)=>e);
表: イテレーション関係
v,v2は整数の配列
mはintをキーにintを値に取る連想配列
itrはintを返すイテレータ
Kotlin | TypeScript | Dart | |
---|---|---|---|
反復文 - indexed | for(i in 1 until 3){ } |
for(let i=0;i<3;i++){ } |
|
反復文 - 要素 | for(e in v){ } |
for(e in v){ } |
for(var e in v){ } |
配列の生成 | v2=v.map{it*2} |
v2=v.map((e)=>e*2) |
v2= v.map((e)=>e*2) .toList() |
リスト平坦化 | v2= v.flatMap{listOf(it)} |
v2= v.expand((e)=>[e]) .toList() |
|
配列要素の逐次処理 | itr = v.map((e)=>e*2) |
||
イテレータから値を取り出す | |||
表: 入出力と文字列フォーマッタ
Kotlin | TypeScript | Dart | |
---|---|---|---|
文字列化して標準出力 | print(v) |
console.log(v) |
print(v); |
差し込み | "$i:${i+1}" |
`${i}:${i+1}` |
"$i:${i+1}" |
~ 基数指定 | i.toString(16) |
i.toString(16) |
|
~ 16進数 | "%x".format(i) |
i.toString(16) |
|
~ 2文字幅(0パディング) | "%02d".format(i) |
`0${i}`.slice(-2) |
"$i".padLeft(2,'0') |
文字列➔Byte配列 | ba=utf8.encode(s) |
||
Byte配列➔文字列 | |||