objective-c のキャストと swift の型変換を比べてみる #akibaswift
TRANSCRIPT
紙版は絶版、電⼦書籍は販売中
NSInteger integerValue = 10; double doubleValue = 128.9;
// 明示キャスト NSUInteger value1 = (NSUInteger)integerValue; NSInteger value2 = (NSInteger)doubleValue; char value3 = (char)integerValue; double value4 = (double)integerValue;
NSInteger integerValue = 10; double doubleValue = 128.9;
// 暗黙キャスト NSUInteger value1 = integerValue; NSInteger value2 = doubleValue; char value3 = integerValue; double value4 = integerValue;
NSInteger integerValue = -8000000000000002345; double doubleValue = 123456789.935;
// 誤差が出るキャスト NSInteger value1 = doubleValue; // 123456789 double value2 = integerValue; // -8000000000000002048 NSUInteger value3 = integerValue; // 10446744073709549271u short value4 = doubleValue; // -13035
doubleValue + floatValue // double floatValue + doubleValue // double doubleValue + longDoubleValue // long double intValue + floatValue // float intValue + charValue // int intValue + longValue // long charValue + shortValue // int
1 / 3.0 // 0.3333333333333333 1 / 3.0f // 0.33333333f 1 / 3 // 0
1 / 3.0 == 1 / 3 // false 1 / 3.0 == 1 / 3.0f // false
int a = 1, b = 3, c = 5, d = 4; // 明示キャストによる制御 c * (a / b * d) // 0 c * (a / (double)b * d) // 6.666666666666666 c * (int)(a / (double)b * d) // 5 (int)(c * ((double)a / b * d)) // 6 c * (double)(a / b) * d // 0
short shortValue = 0x7FFF; long longValue = 0x12345678;
// 再解釈キャスト short value1 = *(short*)&longValue; // 0x5678 long value2 = *(long*)&shortValue; // 0x6080000000207FFF double value3 = *(double*)&longValue; // 1.508974781700064e-315
NSData *data = [[NSMutableData alloc] init];
// アップキャスト NSObject *obj1 = (NSObject*)data;
// ダウンキャスト NSMutableData *obj2 = (NSMutableData*)data;
NSData *data = [[NSMutableData alloc] init];
// アップキャスト NSObject *obj1 = data;
// ダウンキャストは明記が必要 NSMutableData *obj2 = (NSMutableData*)data;
NSString *obj = [[NSString alloc] init];
// 無関係な型へのキャスト NSNumber *number = (NSNumber*)obj;
// メソッドが存在しなければ実行時エラー NSString *text = [number descriptionWithLocale: nil];
id object;
// 可能性の判定 if ([object isKindOfClass:[NSNumber class]]) { // 整合性が約束されればキャストを実施 NSNumber *number = (NSNumber*)object; }
let integerValue: Int = 65 let doubleValue: Double = 128.9
// 型を変換 let value1 = UInt(integerValue) let value2 = Int(doubleValue) let value3 = UnicodeScalar(integerValue) let value4 = Double(integerValue)
let sourceValue: UInt = 18446744073709551615
// 変換できないとき let value1 = Int(sourceValue)
let value2 = Int("120x") // nillet value3 = try MyValue(sourceValue) // Error
let source: UInt = 18446744073709551000
// 型を変換 let value1 = Int(bitPattern: source) // -616 let value2 = Int8(truncatingBitPattern:source) // -104
let source: Int64 = 0x12345678
// 再解釈 var value1 = unsafeBitCast(source, Double.self) // 1.508974781700064e-315
var value2 = unsafeBitCast(source, Int32.self)
as as? as!
let instance: NSData = NSMutableData()
// アップキャスト let object1 = instance as NSObject
// ダウンキャスト let object2 = instance as? NSMutableData let object2 = instance as! NSMutableData
let instance: NSData = NSMutableData()
// アップキャスト let object1: NSObject = instance
// ダウンキャスト let object2 = instance as? NSMutableData let object2 = instance as! NSMutableData
let object = NSString()
// 無関係な型へのキャスト let number1 = object as? NSData // nil
let number2 = object as! NSData // ERROR
(int)value Int(value)
[instance toDouble] Double(instance)
(SubClass*)object (BaseClass*)object
object as? SubClass object as BaseClass
[object isKindOfClass: [SomeClass class]]
if let obj = object as? SomeClass {
*(double*)&value unsafeBitCast(
value, Double.self)
@interface ESMyObject : NSObject
// NSInteger 型から自分の型に変換する - (instancetype)initWithInteger:(NSInteger)value;
@end
@interface ESMyObject : NSObject
// 自分自身から NSInteger に変換 - (NSInteger)toInteger;
@end
// NSInteger から自分自身に変換 ESMyObject *object = [[ESMyObject alloc] initWithInteger: 10]; // 自分自身を NSInteger に変換 NSInteger value = [object toInteger];
@interface ESMyObject : NSObject
// NSLocale からの変換? - (instancetype)initWithLocale:(NSLocale)locale;
// 自分自身から NSPoint への変換? - (NSPoint)toPoint;
@end
struct MyValue { // Int 型から自身の型へ変換するイニシャライザ init(_ value: Int) { } }
extension Int { // MyValue 型から自身の型 (Int) へ変換する init(_ value: MyValue) {
} }
// Int から自分自身に変換 let value = MyValue(100) // 自分自身を Int に変換 let number = Int(value)
struct MyValue { // ラベル名を伴う場合は Full-Width 変換ではない init(locale: NSLocale) {…} // これがもし Full-Width 変換なら // NSPointに変換イニシャライザとして実装したい func toPoint() -> NSPoint {…} }
init / init?init … throws
// 一般に Optional Binding とセットで使う if let number = instance as? NSData {
} else {
// キャストできなかった場合も想定できる }
// 確実にダウンキャスト出来る時にだけ使う let data = instance as! NSData
// キャストできない場合は強制終了 let data = instance as! NSNumber
// 確実にダウンキャスト出来るかを判定 if instance is NSData {
// ここならキャストが確実にできる let data = instance as! NSData
}
let workData = NSMutableData()
// 継承関係より NSData で扱えるのは明らか let data = workData as NSData
// 中身的には NSMutableData 型でも、 let instance: AnyObject = NSMutableData()
// 外見からは NSData にキャスト出来るか分からない// こういうときは as? または as! でのキャストが必要 let data = instance as? NSData
let string = String()
// ブリッジ機構は Swift 標準ライブラリが提供 let objcString = string as NSString
(SubClass*)instance instance as? SubClass
(SubClass*)instance instance as! SubClass
(BaseClass*)instance instance as BaseClass
(BaseClass*)instance instance as? BaseClass
(SomeClass*)instance instance as SomeClass
isKindOfClass: conformsToProtocol: instance is SomeType