0

I have a lot of different types of elements in an array, and I want them all to know how to understand how to render themselves... it's quite complex and I'm always adding new types - don't want to have to do shotgun surgery each time

but can't seem to work out the syntax for inheritance of a function with an opaque type return - if I do this:


class Element
{
   func forDisplay() -> some View 
   { fatalError("this function needs to be overridden")}
}

then try to override it

class TextElement : Element
{
    ...

    override func forDisplay() -> some View
    { return Text( self.textValue ) };
}

It gives me a compile error - and if I just leave out the word override

class TextElement : Element
{
    ...

    func forDisplay() -> some View
    { return Text( self.textValue ) };
}

it compiles fine, runs fine - but then calls the underlying error function

11
  • SwiftUI is Protocol based, not Inheritance based. Element should be a Protocol that the others adopt. Commented Feb 27, 2022 at 21:46
  • elements are complex things - 80% of the code is shared - I don't see how I could use a protocol without duplicating that code Commented Feb 27, 2022 at 21:52
  • actually - I just tried it - and I can't even create a func that returns a view in a protocol - func for_display() -> View and func for_display() -> some View both don't work Commented Feb 27, 2022 at 21:54
  • 1
    The protocol would need an associated type, and forDisplay would return that associated type. Commented Feb 27, 2022 at 21:57
  • 1
    Undo what you just did and use an associated type. AnyView will mess you up later in SwiftUI. You need to read up on Protocols. Commented Feb 27, 2022 at 22:03

1 Answer 1

1

You can't override opaque types. Better just to never subclass anything, really. It's a last resort. I bet you don't even want a reference type and you've only chosen a class because of inheritance, thinking it would model your solution well. Regardless…

Maybe you want a protocol with an associated type as has been recommended, or maybe you just want a generic Element<View: SwiftUI.View>. Trouble with those is, you won't be able to constrain extensions because you won't know what the opaque Views are. So I suspect you'll have more luck with phantom types.

protocol HeadingTag { }
enum H1: HeadingTag { }
enum H2: HeadingTag { }
enum H3: HeadingTag { }
class Element<Tag> {
extension Element where Tag: HeadingTag  {
  func forDisplay() -> some View {
    Text(textValue)
  }
}
extension Element where Tag == H2 {
  func forDisplay() -> some View {
    // An H2-specific view
Sign up to request clarification or add additional context in comments.

1 Comment

interesting - will think about this - thanks

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.