Skip to content

Instantly share code, notes, and snippets.

@jazzychad
Last active August 29, 2015 14:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jazzychad/68c12d4fce65e543ede4 to your computer and use it in GitHub Desktop.
Save jazzychad/68c12d4fce65e543ede4 to your computer and use it in GitHub Desktop.
// why does this not compile?
// Book implements BookRenderable
// so why does the compiler complain when Library.books is a [Book] and LibraryRenderable is looking for [BookRenderable] ??
protocol LibraryRenderable {
var address : String? { get }
var books : [BookRenderable]? { get }
}
protocol BookRenderable {
var title : String? { get }
var author : String? { get }
}
struct MockLibrary : LibraryRenderable {
let address = "123 Main Street"
let books = [MockBook(), MockBook()]
}
struct MockBook : BookRenderable {
let title : String? = "Ender's Game"
let author : String? = "Orson Scott Card"
}
class Library : LibraryRenderable {
var address : String?
var books : [Book]? // <---- compiler complains "does not conform to LibraryRenderable"
}
class Book : BookRenderable {
var title : String?
var author : String?
}
// making this work with protocol typealiases
// the following compiles cleanly
protocol LibraryRenderable {
typealias BookType : BookRenderable
var address : String? { get }
var books : [BookType]? { get }
}
protocol BookRenderable {
var title : String? { get }
var author : String? { get }
}
struct MockLibrary : LibraryRenderable {
typealias BookType = MockBook
let address : String? = "123 Main Street"
let books : [MockBook]? = [MockBook(), MockBook()]
}
struct MockBook : BookRenderable {
let title : String? = "Ender's Game"
let author : String? = "Orson Scott Card"
}
class Library : LibraryRenderable {
typealias BookType = Book
var address : String?
var books : [Book]?
}
class Book : BookRenderable {
var title : String?
var author : String?
}
@simonexmachina
Copy link

Wow, I agree that that is really unexpected.

I'm okay with the requirement that Library.books should be of type [BookRenderable]?, but it's a real problem that MockLibrary.books can't contain MockBook instances.

Is there a solution using generics?

I'd be really interested to learn more about this issue.

@simonexmachina
Copy link

I just went through this with my colleague and I was mistaken - the MockLibrary.books can contain MockBook instances. So I'm happy with this.

I agree that it would be better if Library.books could be of type [Book]?, and I'm pretty sure this is how it works in Java, but it's a language design decision, and I'm okay with working with the decision they've made.

@simonexmachina
Copy link

I've just confirmed that they did make the same design decision in Java too:

package sandbox;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

interface LibraryRenderable {
    List<BookRenderable> getBooks();
}

interface BookRenderable {}

class MockLibrary implements LibraryRenderable {
    @Override
    public List<BookRenderable> getBooks() {
        return new ArrayList<BookRenderable>(Arrays.asList(new BookRenderable[] {new MockBook()}));
    }
}

class MockBook implements BookRenderable {
}

class Library implements LibraryRenderable {
    @Override
    public List<BookRenderable> getBooks() {
        return new ArrayList<BookRenderable>(Arrays.asList(new BookRenderable[] {new Book()}));
    }
}

class Book implements BookRenderable {}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment