Created
June 7, 2014 17:46
-
-
Save n8gray/15224c6e77e080c072af to your computer and use it in GitHub Desktop.
Testing Swift array variance
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// ArrayTest.swift | |
// SwiftTest | |
// | |
// Swift array subtyping semantics test | |
// | |
// Created by Nathan Gray on 6/7/14. | |
// Copyright (c) 2014 Mellmo. All rights reserved. | |
// | |
import Foundation | |
// A base class | |
class Base {} | |
// A couple of subclasses | |
class Sub1 : Base { | |
var name : String = "Nobody" | |
init(name:String) { self.name = name } | |
} | |
class Sub2 : Base { | |
var age : Int = 1 | |
} | |
// A silly function to test upcasting | |
func tupleDuple(x : Base) -> (Base, Base) { | |
return (x, x) | |
} | |
// A simple function that takes a read-only array | |
func sub(arr : Base[], i : Int) -> Base { | |
return arr[i]; | |
} | |
// A simple function that mutates an array | |
func append(inout arr : Base[], x : Base) { | |
arr += x | |
} | |
// A polymorphic function that mutates an array | |
func polyAppend<T>(inout arr : T[], x : T) { | |
arr += x | |
} | |
// // // // // // // // // // // // // // // // // // // // // // // // | |
func arrayTestMain() { | |
// This works, demonstrating that implicit upcasts of function arguments are allowed | |
let tup = tupleDuple(Sub1(name:"Twin")) | |
// Make an array of subclass objects | |
var arr = Sub1[]() | |
arr += Sub1(name:"Alice") | |
arr += Sub1(name:"Joe") | |
// This should work, simply substitute Sub1 for T | |
polyAppend(&arr, Sub1(name:"Bob")) | |
// This should also work, since the array is passed read-only | |
// It's actually "copied", but semantically it's read-only -- passing it in | |
// will not cause it to be mutated. | |
var x = sub(arr, 0) | |
// These are unsafe and should both fail... | |
append(&arr as Base[], Sub2() as Base) | |
polyAppend(&arr as Base[], Sub2() as Base) | |
// Hooray! Both of them fail to compile, even with explicit casts! | |
// Java famously got this wrong and allows passing a | |
// mutable array of Sub1 to a function that expects an array of Base. | |
// This forces them to do runtime safety checks on *every* array subscript. | |
for s1 in arr { | |
println("Hello \(s1.name)") | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment