Testing Swift array variance
// | |
// 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