0
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Swift】is, as?, as!について

Posted at

はじめに

is,as?,as!の使い所が合っているのか疑問に思い調べてみました。

isas

MediaItem クラス
class MediaItem {
    var name: String
    init(name: String) {
        self.name = name
    }
}
Movie/Song クラス
class Movie: MediaItem {
    var director: String
    init(name: String, director: String) {
        self.director = director
        super.init(name: name)
    }
}

class Song: MediaItem {
    var artist: String
    init(name: String, artist: String) {
        self.artist = artist
        super.init(name: name)
    }
}
library: [MediaItem]
let library = [
    Movie(name: "Casablanca", director: "Michael Curtiz"),
    Song(name: "Blue Suede Shoes", artist: "Elvis Presley"),
    Movie(name: "Citizen Kane", director: "Orson Welles"),
    Song(name: "The One And Only", artist: "Chesney Hawkes"),
    Song(name: "Never Gonna Give You Up", artist: "Rick Astley")
]

is

あるインスタンスが特定のサブクラス型であるかどうかを調べるには、型チェック演算子 (is) を使用する。インスタンスがそのサブクラスの型であればtrueが返る。

var movieCount = 0
var songCount = 0

for item in library {
    if item is Movie {
        movieCount += 1
    } else if item is Song {
        songCount += 1
    }
}

print("Media library contains \(movieCount) movies and \(songCount) songs")
// Prints "Media library contains 2 movies and 3 songs"

as?oras!

あるクラス型の定数や変数が、実は裏ではサブクラスのインスタンスを参照していることがあり、このような場合に型キャスト演算子 (as? または as!) を使用してサブクラスの型にダウンキャストすることができる。

ダウンキャストが成功するかどうかわからない場合は、as?
常にオプションの値を返し、ダウンキャストに失敗した場合はnilになる。これにより、ダウンキャストが成功したかどうかを確認することができる。

ダウンキャストが必ず成功すると確信できる場合は、as!
不正なクラス型にダウンキャストしようとして失敗すると、実行時エラーになる。

for item in library {
    if let movie = item as? Movie {
        print("Movie: \(movie.name), dir. \(movie.director)")
    } else if let song = item as? Song {
        print("Song: \(song.name), by \(song.artist)")
    }
}

// Movie: Casablanca, dir. Michael Curtiz
// Song: Blue Suede Shoes, by Elvis Presley
// Movie: Citizen Kane, dir. Orson Welles
// Song: The One And Only, by Chesney Hawkes
// Song: Never Gonna Give You Up, by Rick Astley

※ キャスティングは、実際にインスタンスを変更したり、その値を変更したりするものではなく、基本的なインスタンスはそのままで、単にキャストされた型のインスタンスとして扱われ、アクセスされるだけ

AnyAnyObject

Anyは、関数型を含む、まったく任意の型のインスタンスを表す
AnyObjectは、任意のクラス型のインスタンスを表す

things: [Any]
var things: [Any] = []

things.append(0)
things.append(0.0)
things.append(42)
things.append(3.14159)
things.append("hello")
things.append((3.0, 5.0))
things.append(Movie(name: "Ghostbusters", director: "Ivan Reitman"))
things.append({ (name: String) -> String in "Hello, \(name)" })

Any型は、オプショナル型を含むあらゆる型の値を表すが、SwiftはAny型の値が期待される場所でオプショナル値を使用すると警告を表示するため、オプショナル値を Any 値として使用する必要がある場合、以下のようにオプショナル値を明示的に Anyにキャストするためにasを使用する

let optionalNumber: Int? = 3
things.append(optionalNumber)        // Warning
things.append(optionalNumber as Any) // No warning

AnyまたはAnyObjectであることが分かっている定数または変数の特定の型を検出するには、switch文のcaseでis またはasを使用する

for thing in things {
    switch thing {
    case 0 as Int:
        print("zero as an Int")
    case 0 as Double:
        print("zero as a Double")
    case let someInt as Int:
        print("an integer value of \(someInt)")
    case let someDouble as Double where someDouble > 0:
        print("a positive double value of \(someDouble)")
    case is Double:
        print("some other double value that I don't want to print")
    case let someString as String:
        print("a string value of \"\(someString)\"")
    case let (x, y) as (Double, Double):
        print("an (x, y) point at \(x), \(y)")
    case let movie as Movie:
        print("a movie called \(movie.name), dir. \(movie.director)")
    case let stringConverter as (String) -> String:
        print(stringConverter("Michael"))
    default:
        print("something else")
    }
}

// zero as an Int
// zero as a Double
// an integer value of 42
// a positive double value of 3.14159
// a string value of "hello"
// an (x, y) point at 3.0, 5.0
// a movie called Ghostbusters, dir. Ivan Reitman
// Hello, Michael

おわりに

AnyまたはAnyObjectの値をswitchで型キャストする実装はやったことがないので、使っていけたら便利なのかもと思いました。

参照

0
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?