Object-Oriented Programming for Smartypants-DART EDITION. Part II ~Abstraction~
In the previous episode of OOP for smartypants, we discussed Inheritance as the first pillar of Object Oriented Programming.
In this article, we will discuss another pillar of OOP which is Abstraction.
How Abstraction Works
Whenever Sony or LG decides to make a DVD player, they build it with a lot of complex working parts and sophisticated electronics. These parts are all inside the player. On the outside however is just a plastic case, some buttons on the front panel and a plastic tray which accepts our disks. These parts are the ones we can see.
Abstraction works very much like this DVD player. It is the idea of building complex systems by creating smaller distinct pieces that have defined roles so that we can easily manage this complexity. Abstraction does the following:
- It uses simple things to depict complexity.
- It obscures complexity from the user, allowing them to only interact with specific attributes and methods.
In short, we don't have to know what's going on inside of the DVD player, all we have to do is press the buttons, and Voila! It works.
Let's take an example of an app that helps students prepare for a Biology exam using true-or-false questions. We'll require an interface with which our user interacts, it'll allow the user to read the question and choose either true or false. We'll also need a question bank, where all our questions and their corresponding answers will be stored.
Inside our lib folder, let's create a dart file. Call it question.dart
class Question{
String questionText;
bool questionAnswer
Question(this.questionText,this.questionAnswer);
}
This is simply our Question class, we'll use this class to create Question objects later, specifying both the question and its correct answer. Inside the lib folder, again create a file. Call it quiz_bank.dart, this will hold all our list of questions that will be displayed one after the other.
import 'question.dart';
class QuizBank{
int questionNumber=0;
List <Question> question =[
Question('The largest human organ is the skin', true),
Question('Honey is the sugary substance that insects get from flowers', false),
Question('Aspirin was originally derived from the willow tree', true),
Question('Antibodies are produced by red blood cells', false),
Question('Blood is produced in the bones', true),
]
void nextQuestion(){
questionNumber++;
}
String getQuestionText(){
return question[questionNumber].questionText;
}
bool getQuestionAnswer(){
return question[questionNumber].questionAnswer;
}
}
Here we've created a QuizBank class. This is the Brain of the app, we created a list called question which stores a list of Question objects, each object has two arguments, a questionText and a questionAnswer. We've also declared a questionNumber variable that will serve as our counter to help us iterate through the list. The three methods nextQuestion, getQuestionText and getQuestionAnswer increment questionNumber,return questionText and return questionAnswer respectively.
The main interface.
Inside the main.dart, we have our user interface(the displayed question and the true or false options for our user to pick). This is the only part our user sees.
import 'package:flutter/material.dart';
import 'quiz_bank.dart';
void main() => runApp(QuizApp());
class QuizApp{
QuizBank quizBank=QuizBank();
void checkAnswer(bool userAnswer){
setState((){
bool correctAnswer=quizBank.getQuestionAnswer;
if(userAnswer==correctAnswer){
return Text('Correct');
}else{
return Text('Wrong')
}
});
}
quizBank.nextQuestion();
@override
Widget buid(BuildContext context){
return MaterialApp{
home:Scaffold(
body:Column(
children: [
Expanded(
child:Text(quizBank.getQuestion());
),
Expanded(
child:FlatButton(
child:Text('TRUE'),
OnPressed: () {
checkAnswer(true);
}
)
),
Expanded(
child:FlatButton(
child:Text('FALSE'),
OnPressed: () {
checkAnswer(false);
}
)
),
]
)
)
}
}
}
Why Abstraction?
Observe how our code, instead of being contained solely in a single file that's several lines long is actually divided up into three files.
One file handles the creation of our Question class and does only that. The second holds all our questions and the methods needed to access them. The final one has our simple user's interface.
In our main.dart file. Our user Interface has been created using simple widgets. We are displaying each question one after the other by accessing the question list using an object. Then we assess whether the their answer is correct and move on to the next question.
Hence, we've used smaller seperate pieces of code, each with a defined role to manage our larger piece of code.
Voila, Abstraction!
Our next pillar of OOP to be discussed is Encapsulation. Stay tuned!
Thanks for Reading!!