2016-09-04 9 views
1

私は最近、インスタンスが親クラス内で作成されている間に、クラスのインスタンスをサブクラスに変換するのが非常に便利なケースを見つけました。しかし、私はそのようなことを見たことがない。それが不可能な場合クラスのインスタンスをサブクラスのインスタンスに変換することは可能ですか?

class Foo { 
    var name: String 
} 

class Bar: Foo { 
    var friendName: String 
} 

let foo = Foo(name: "Alice") 
foo.toBar(friendName: "Bob") 
// foo now of type Bar, as if I'd done 
// foo = Bar(name: "Alice", friendName: "Bob") 

、これは設計の観点からは不可能であろういくつかの理由がある:だからのような何かをする方法はありますか?

===編集===それだけのプレビューで上の感覚

レッツは、この本のために同じデータベースレコードに対応するもの表す2つのビューがあると言う作ることができユースケースの説明本と別のものはもっと複雑な視点です。モデルは次のようになります。

protocol BookMetaDelegate { 
    func onReadStatusUpdate() 
} 

/// describe a book 
class BookMeta { 
    var delegate: BookMetaDelegate? 
    private var _hasBeenRead: Bool 
    var hasBeenRead: Bool { 
    get { 
     return _hasBeenRead 
    } 
    set { 
     guard newValue != _hasBeenRead else { return } 
     _hasBeenRead = newValue 
     delegate?.onReadStatusUpdate() 
    } 
    } 
    var title: String 
} 

/// contains all the content of a book 
class Book: BookMeta { 
    var content: BookContent 
    var lastPageRead: Int 

    /// some logic that only makes sense in a Book instance 
    func getLastPageRead() { 
    return content.getPage(lastPageRead) 
    } 
} 

とビューは次のようになります。物事はそれについての詳細を考える

fetch(bookMetaWithId: 123).then { bookMeta in // bookMeta is of type BookMeta 
    let preview = BookPreview(book: bookMeta) 
    ... 

    fetch(contentOf: bookMeta).then { content, lastPageRead in 
    bookMeta.asBook(content: content, lastPageRead: lastPageRead) 
    let bookView = BookView(book: bookMeta) // doing so will change the hasBeenRead flag and message the instance's delegate, ie the preview 
    ... 
    } 
} 
+0

いいえ、不可能です。既存の 'Foo'から* new *' Bar'を作成することは可能ですが、既存のオブジェクトのタイプを変更することはできません。そうすることでメリットはありません。 –

+0

そうすることでなぜメリットがないのでしょうか?それはより多くの視点です。ユーザーのプロファイルを表す2つのクラスと、他の多くの情報を持つユーザーがあるとしましょう。最初にプロファイルをロードし、後で他の情報を取得します。私はその後、余分なデータを使って自分のUserProfileインスタンスをダウンキャストしたいかもしれません。 – Guig

+1

"ダウンキャスト"を間違って使用しています - あなたはオブジェクトの実際のタイプにダウンキャストします。あなたの例では、新しいオブジェクトを作成することや、元のクラスの "その他の情報"オプションのプロパティにすることに利点はありません。だからこそ利益はないのです。 「ユーザーのプロファイルを表す2つのクラスと他の多くの情報を持つユーザー」を持つことが実際の問題のようです。より良いデザインを作成することは、タイプシステムを完全に破るよりはるかに賢明です。 –

答えて

0

のように起こることができるようなことが可能であった場合

class BookPreview: UIView, BookMetaDelegate { 
    var book: BookMeta 
    init(book: BookMeta) { 
    book.delegate = self 
    } 
    func onReadStatusUpdate() { 
    print("read status has changed! UI should update") 
    } 
} 

class BookView: UIView { 
    var book: Book 
    init(book: Book) { 
    book.hasBeenRead = true 
    } 
} 

その後、それはそのように聞こえます

class Foo { 
    var name: String 
} 

class Bar: Foo { 
    var friendName: String 
} 

class Bla: Foo { 
    var surname: String 
} 

func something(foo: Foo) { 
    foo.toBla(surname: "Will") 
} 

let bar = Bar(name: "Alice", friendName: "Bob") 
something(foo: bar) // what does that do ??? is bar a Bla now ? 

これはそのような鋳造を不可能にするのに十分な理由であろう。

関連する問題