Search code examples
flutterdartsoftware-designsolid-principles

Liskov Substitution Principle: Confusion about additional Functionalities of sub types


I'm working on a social app using flutter, so there are posts to get published. Suppose there are two types of posts.

  • Post contains only text.
  • ImagePost contains images and text.

The following code is an example to demonstrate the problem.

class Post{
  
  String text;
  Post(this.text);
}

class ImagePost extends Post{

  String image;
  ImagePost(this.image, super.text);
}

void printy(Post p){ // p can be a Post or ImagePost
  
  print(p.text);

// for now, it's conformation to LSP

  if(p.runtimeType == ImagePost){
  print(p.image ); // error: cause Post (p) doesn't contain image field
}
}

void main() {
  Post post = Post('hi there');
  ImagePost imagePost = ImagePost('dumy link' , 'welcome');
  printy(imagePost);
} 

The above code should conform to the Liskov Substitution Principle: Subtypes must be substitutable for their base types; but there's an additional attribute image inside ImagePost which I need to access inside the method printy. I can't because the Post p parameter doesn't contain an image.

I could bypass that problem by defining a printy method in the base class and overriding it in subclasses; but there's no printy method in the real project. It has a separate postBuilder that needs to access the image to render it on the screen, if the post is an ImagePost.

In short: how can I access the image property inside a separate printy client, when the post is an ImagePost?


Solution

  • Use is to check for object type. The object tested will become the second operand (the type) inside the if scope.

    if (p is ImagePost) {
      // p is now an ImagePost in this scope
      print(p.image); // You can access the `image` property
    }
    

    See also: