Mastering Object-Oriented Programming (OOP) Concepts in Flutter
Learn about classes, objects, inheritance, encapsulation, polymorphism, abstraction, constructors, getters, setters, interfaces, static members, composition, and more.
Explore and master all essential Object-Oriented Programming (OOP) concepts in Flutter.
Real-time examples provided for a thorough understanding.
Classes and Objects
Class: A class is like a blueprint or a recipe that defines how an object should be created and what it can do.
Object: An object is a concrete instance created based on the class blueprint, having its own unique state and behavior.
- Understanding Classes and Objects in Dart and Flutter.
- Creating and Instantiating Objects.
- Utilizing Class Members (Fields and Methods).
- Exploring Constructors for Object Initialization.
class Person {
String name;
int age;
void sayHello() {
print("Hello, I'm $name and I'm $age years old.");
}
}
void main() {
var person1 = Person();
person1.name = "John";
person1.age = 30;
person1.sayHello(); // Output: Hello, I'm John and I'm 30 years old.
}
..
Inheritance
Inheritance is the process of one class inheriting the properties and methods of another class. This allows us to reuse code and to create more complex and powerful classes.
- Implementing Inheritance for Code Reusability.
- Overriding Methods in Subclasses.
- Abstract Classes and Methods.
- Achieving Multiple Inheritances through Interfaces.
class Animal {
void makeSound() {
print("Animal makes a sound.");
}
}
class Dog extends Animal {
@override
void makeSound() {
print("Dog barks.");
}
}
void main() {
var dog = Dog();
dog.makeSound(); // Output: Dog barks.
}
..
Encapsulation
Encapsulation is the process of grouping together related data and methods into a single unit. This makes it easier to manage the data and methods, and it also helps to protect the data from unauthorized access.
- Understanding Encapsulation and Access Modifiers (public, private, protected).
- Using Getters and Setters to Control Object State.
class Person {
String _name; // Private data member
int _age;
Person(this._name, this._age);
// Getter for name
String get name => _name;
// Getter for age
int get age => _age;
// Setter for age
void set age(int newAge) {
if (newAge > 0 && newAge <= 120) {
_age = newAge;
} else {
print("Error: Invalid age.");
}
}
void sayHello() {
print("Hello, my name is $_name, and I am $_age years old.");
}
}
void main() {
var person = Person("John", 30);
person.sayHello(); // Output: Hello, my name is John, and I am 30 years old.
person.age = 35;
person.sayHello(); // Output: Hello, my name is John, and I am 35 years old.
person.age = -5; // Output: Error: Invalid age.
}
..
Polymorphism
Polymorphism is the ability of an object to take on different forms. This is achieved by having a common interface for different types of objects.
class Animal {
void makeSound() {
print("Animal makes a sound.");
}
}
class Dog extends Animal {
@override
void makeSound() {
print("Dog barks.");
}
}
class Cat extends Animal {
@override
void makeSound() {
print("Cat meows.");
}
}
void main() {
Animal animal1 = Dog();
Animal animal2 = Cat();
animal1.makeSound(); // Output: Dog barks.
animal2.makeSound(); // Output: Cat meows.
}
..
Abstraction
Abstraction is the process of hiding the implementation details of a class from the outside world. This allows us to focus on the essential features of a class, without having to worry about the details of how the class works.
abstract class Animal {
void makeSound();
}
class Dog extends Animal {
@override
void makeSound() {
print("Dog barks.");
}
}
void main() {
var dog = Dog();
dog.makeSound(); // Output: Dog barks.
}
..
Constructors
Constructors are special methods used to initialize objects when they are created. In Flutter, constructors are essential for setting up the initial state of widgets.
Let's see an example of using constructors to initialize a custom widget:
import 'package:flutter/material.dart';
class MyCustomButton extends StatelessWidget {
final String label;
final Function onPressed;
MyCustomButton({required this.label, required this.onPressed});
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: onPressed,
child: Text(label),
);
}
}
void main() {
runApp(
MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("Custom Button Example"),
),
body: Center(
child: MyCustomButton(
label: "Click Me!",
onPressed: () {
print("Button clicked!");
},
),
),
),
),
);
}
In this example, we create a custom button widget called MyCustomButton, which takes two required parameters label and onPressed. The constructor is used to initialize the widget with these values, making it easy to create and reuse the custom button throughout the app.
..
Interfaces
Interface is a contract that defines a set of methods that a class must implement. This can be used to achieve polymorphism in Flutter.
Let's create an example:
interface class Shape {
void draw(){};
}
class Circle implements Shape {
@override
void draw() {
print("Drawing a circle.");
}
}
class Square implements Shape {
@override
void draw() {
print("Drawing a square.");
}
}
void main() {
Shape circle = Circle();
circle.draw(); // Output: Drawing a circle.
Shape square = Square();
square.draw(); // Output: Drawing a square.
}
In this example, we create an abstract class Shape with an abstract method draw(). Then, we have two classes Circle and Square, both of which implement the Shape interface (abstract class) and provide their own implementation for the draw() method.
..
Static Members
Static members belong to the class rather than to an instance of the class. They are shared among all instances of the class and do not require object creation to access them.
Some advantages:
- Global Accessibility
- Shared Data
- Memory Efficiency
- Code Organization
- Ease of Use
In this example, we'll demonstrate how to utilize static members in Flutter to handle common utilities like a welcome message and a function for formatting dates.
import 'package:flutter/material.dart';
// Creating a class to hold static members for common utilities
class AppUtilities {
static const String welcomeMessage = 'Welcome to our App!'; // Static constant for the welcome message
// Static method to format a DateTime object to a string
static String formatDate(DateTime date) {
return '${date.day}-${date.month}-${date.year}'; // Format: day-month-year
}
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: HomePage(),
);
}
}
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
DateTime currentDate = DateTime.now(); // Getting the current date and time
String formattedDate = AppUtilities.formatDate(currentDate); // Formatting the current date using the static method
return Scaffold(
appBar: AppBar(
title: Text('App Home Page'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
AppUtilities.welcomeMessage, // Displaying the welcome message using the static constant
style: TextStyle(fontSize: 20),
),
SizedBox(height: 20),
Text(
'Today\'s Date: $formattedDate', // Displaying the formatted date
style: TextStyle(fontSize: 18),
),
],
),
),
);
}
}
..
Composition
Composition in Flutter refers to the process of combining multiple widgets to create a more complex and complete user interface.
It involves creating custom widgets by nesting or combining existing widgets to build the desired UI.
Some advantages:
- Reusability
- Code Clarity
- Encapsulation
- Performance Optimization
- Flutter's Widget Ecosystem
- Design Consistency
- Testability
Let's create an example :
import 'package:flutter/material.dart';
void main() {
runApp(BlogApp());
}
class BlogApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: BlogPost(),
);
}
}
class BlogPost extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter Blog'), // AppBar with the title 'Flutter Blog'
),
body: Container(
padding: EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
BlogTitle(title: 'Sample Blog Post'), // Custom widget for blog title
BlogMeta(author: 'John Doe', date: 'July 23, 2023'), // Custom widget for blog meta information
SizedBox(height: 16.0),
BlogContent(content: 'This is the content of the blog post...'), // Custom widget for blog content
],
),
),
);
}
}
class BlogTitle extends StatelessWidget {
final String title;
BlogTitle({required this.title});
@override
Widget build(BuildContext context) {
return Text(
title,
style: TextStyle(
fontSize: 24.0,
fontWeight: FontWeight.bold,
),
);
}
}
class BlogMeta extends StatelessWidget {
final String author;
final String date;
BlogMeta({required this.author, required this.date});
@override
Widget build(BuildContext context) {
return Text(
'By $author - $date',
style: TextStyle(
color: Colors.grey,
),
);
}
}
class BlogContent extends StatelessWidget {
final String content;
BlogContent({required this.content});
@override
Widget build(BuildContext context) {
return Text(content); // Displaying the blog content
}
}
..
Comments
Post a Comment