added resources, coding challenges, and more study guides
This commit is contained in:
@@ -1,192 +0,0 @@
|
||||
# Class Constructors in Dart and Flutter: A Comprehensive Guide
|
||||
|
||||
Constructors are special methods used to create and initialize objects of a class. Dart offers several types of constructors to cater to different initialization needs. This guide will cover the main types of constructors in Dart and their usage.
|
||||
|
||||
## 1. Default Constructor
|
||||
|
||||
If you don't declare a constructor, Dart provides a default (no-argument) constructor.
|
||||
|
||||
### Example:
|
||||
|
||||
```dart
|
||||
class Point {
|
||||
double x = 0;
|
||||
double y = 0;
|
||||
}
|
||||
|
||||
void main() {
|
||||
var point = Point(); // Uses the default constructor
|
||||
print('${point.x}, ${point.y}'); // Output: 0, 0
|
||||
}
|
||||
```
|
||||
|
||||
## 2. Named Constructor
|
||||
|
||||
You can define multiple constructors for a class using named constructors.
|
||||
|
||||
### Example:
|
||||
|
||||
```dart
|
||||
class Point {
|
||||
double x, y;
|
||||
|
||||
Point(this.x, this.y);
|
||||
|
||||
// Named constructor
|
||||
Point.origin() {
|
||||
x = 0;
|
||||
y = 0;
|
||||
}
|
||||
|
||||
// Another named constructor
|
||||
Point.fromJson(Map<String, double> json) {
|
||||
x = json['x']!;
|
||||
y = json['y']!;
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
var p1 = Point(2, 3);
|
||||
var p2 = Point.origin();
|
||||
var p3 = Point.fromJson({'x': 1, 'y': 2});
|
||||
|
||||
print('p1: ${p1.x}, ${p1.y}'); // Output: p1: 2, 3
|
||||
print('p2: ${p2.x}, ${p2.y}'); // Output: p2: 0, 0
|
||||
print('p3: ${p3.x}, ${p3.y}'); // Output: p3: 1, 2
|
||||
}
|
||||
```
|
||||
|
||||
## 3. Parameterized Constructor
|
||||
|
||||
This is the most common type of constructor, which accepts parameters to initialize the object's properties.
|
||||
|
||||
### Example:
|
||||
|
||||
```dart
|
||||
class Person {
|
||||
String name;
|
||||
int age;
|
||||
|
||||
Person(this.name, this.age);
|
||||
}
|
||||
|
||||
void main() {
|
||||
var person = Person('Alice', 30);
|
||||
print('${person.name} is ${person.age} years old');
|
||||
// Output: Alice is 30 years old
|
||||
}
|
||||
```
|
||||
|
||||
## 4. Optional Parameters Constructor
|
||||
|
||||
Constructors can have optional parameters, either positional or named.
|
||||
|
||||
### Example:
|
||||
|
||||
```dart
|
||||
class Rectangle {
|
||||
double width;
|
||||
double height;
|
||||
|
||||
// Constructor with optional named parameters
|
||||
Rectangle({this.width = 0, this.height = 0});
|
||||
|
||||
// Constructor with optional positional parameter
|
||||
// Rectangle([this.width = 0, this.height = 0]);
|
||||
}
|
||||
|
||||
void main() {
|
||||
var rect1 = Rectangle(width: 10, height: 20);
|
||||
var rect2 = Rectangle(width: 15);
|
||||
var rect3 = Rectangle();
|
||||
|
||||
print('rect1: ${rect1.width} x ${rect1.height}'); // Output: rect1: 10 x 20
|
||||
print('rect2: ${rect2.width} x ${rect2.height}'); // Output: rect2: 15 x 0
|
||||
print('rect3: ${rect3.width} x ${rect3.height}'); // Output: rect3: 0 x 0
|
||||
}
|
||||
```
|
||||
|
||||
## 5. Initializer List
|
||||
|
||||
You can initialize instance variables before the constructor body runs using an initializer list.
|
||||
|
||||
### Example:
|
||||
|
||||
```dart
|
||||
class Point {
|
||||
final double x;
|
||||
final double y;
|
||||
final double distanceFromOrigin;
|
||||
|
||||
Point(double x, double y)
|
||||
: x = x,
|
||||
y = y,
|
||||
distanceFromOrigin = sqrt(x * x + y * y);
|
||||
}
|
||||
|
||||
void main() {
|
||||
var point = Point(3, 4);
|
||||
print('Distance from origin: ${point.distanceFromOrigin}');
|
||||
// Output: Distance from origin: 5.0
|
||||
}
|
||||
```
|
||||
|
||||
## 6. Factory Constructor
|
||||
|
||||
Factory constructors can return an instance that might not be a new instance of the class.
|
||||
|
||||
### Example:
|
||||
|
||||
```dart
|
||||
class Logger {
|
||||
final String name;
|
||||
static final Map<String, Logger> _cache = <String, Logger>{};
|
||||
|
||||
factory Logger(String name) {
|
||||
return _cache.putIfAbsent(name, () => Logger._internal(name));
|
||||
}
|
||||
|
||||
Logger._internal(this.name);
|
||||
|
||||
void log(String msg) {
|
||||
print('$name: $msg');
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
var logger1 = Logger('UI');
|
||||
var logger2 = Logger('UI');
|
||||
print(identical(logger1, logger2)); // Output: true
|
||||
|
||||
logger1.log('Button clicked');
|
||||
logger2.log('Page loaded');
|
||||
// Output:
|
||||
// UI: Button clicked
|
||||
// UI: Page loaded
|
||||
}
|
||||
```
|
||||
|
||||
## 7. Const Constructor
|
||||
|
||||
For classes whose objects never change, you can define a const constructor.
|
||||
|
||||
### Example:
|
||||
|
||||
```dart
|
||||
class ImmutablePoint {
|
||||
final int x;
|
||||
final int y;
|
||||
|
||||
const ImmutablePoint(this.x, this.y);
|
||||
}
|
||||
|
||||
void main() {
|
||||
var p1 = const ImmutablePoint(1, 2);
|
||||
var p2 = const ImmutablePoint(1, 2);
|
||||
print(identical(p1, p2)); // Output: true
|
||||
}
|
||||
```
|
||||
|
||||
## Conclusion
|
||||
|
||||
Understanding these different types of constructors in Dart and Flutter allows you to create flexible and efficient class initializations. Each type serves a specific purpose, from simple object creation to complex initialization scenarios. Practice using these constructors in your Dart and Flutter projects to become proficient in object-oriented programming with these languages.
|
||||
@@ -1,181 +0,0 @@
|
||||
# Object-Oriented Programming Concepts in Dart and Flutter
|
||||
|
||||
## 1. Abstraction
|
||||
|
||||
Abstraction is the process of hiding complex implementation details and showing only the essential features of an object.
|
||||
|
||||
### Key Points:
|
||||
- Abstraction focuses on what an object does rather than how it does it.
|
||||
- In Dart, abstraction is achieved using abstract classes and interfaces.
|
||||
|
||||
### Example:
|
||||
|
||||
```dart
|
||||
// Abstract class
|
||||
abstract class Shape {
|
||||
double calculateArea();
|
||||
double calculatePerimeter();
|
||||
}
|
||||
|
||||
// Concrete implementation
|
||||
class Circle extends Shape {
|
||||
double radius;
|
||||
|
||||
Circle(this.radius);
|
||||
|
||||
@override
|
||||
double calculateArea() {
|
||||
return 3.14 * radius * radius;
|
||||
}
|
||||
|
||||
@override
|
||||
double calculatePerimeter() {
|
||||
return 2 * 3.14 * radius;
|
||||
}
|
||||
}
|
||||
|
||||
// Usage
|
||||
Shape circle = Circle(5);
|
||||
print(circle.calculateArea()); // Output: 78.5
|
||||
```
|
||||
|
||||
In this example, `Shape` is an abstract class that defines a common interface for all shapes. The `Circle` class provides concrete implementations of the abstract methods.
|
||||
|
||||
## 2. Encapsulation
|
||||
|
||||
Encapsulation is the bundling of data and the methods that operate on that data within a single unit (class). It restricts direct access to some of an object's components.
|
||||
|
||||
### Key Points:
|
||||
- In Dart, encapsulation is achieved using private variables and methods.
|
||||
- Private members are denoted by prefixing an underscore (_) to the identifier.
|
||||
|
||||
### Example:
|
||||
|
||||
```dart
|
||||
class BankAccount {
|
||||
String _accountNumber;
|
||||
double _balance;
|
||||
|
||||
BankAccount(this._accountNumber, this._balance);
|
||||
|
||||
double getBalance() {
|
||||
return _balance;
|
||||
}
|
||||
|
||||
void deposit(double amount) {
|
||||
if (amount > 0) {
|
||||
_balance += amount;
|
||||
}
|
||||
}
|
||||
|
||||
bool withdraw(double amount) {
|
||||
if (amount > 0 && _balance >= amount) {
|
||||
_balance -= amount;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Usage
|
||||
var account = BankAccount('123456', 1000);
|
||||
account.deposit(500);
|
||||
print(account.getBalance()); // Output: 1500
|
||||
```
|
||||
|
||||
In this example, `_accountNumber` and `_balance` are private variables. They can only be accessed and modified through public methods like `getBalance()`, `deposit()`, and `withdraw()`.
|
||||
|
||||
## 3. Inheritance
|
||||
|
||||
Inheritance is a mechanism where a new class is derived from an existing class, inheriting its properties and methods.
|
||||
|
||||
### Key Points:
|
||||
- Dart supports single inheritance, where a class can only inherit from one superclass.
|
||||
- The `extends` keyword is used to create a child class.
|
||||
- The `super` keyword is used to refer to the parent class.
|
||||
|
||||
### Example:
|
||||
|
||||
```dart
|
||||
class Animal {
|
||||
void breathe() {
|
||||
print('Breathing...');
|
||||
}
|
||||
}
|
||||
|
||||
class Mammal extends Animal {
|
||||
void walk() {
|
||||
print('Walking...');
|
||||
}
|
||||
}
|
||||
|
||||
class Dog extends Mammal {
|
||||
void bark() {
|
||||
print('Woof!');
|
||||
}
|
||||
}
|
||||
|
||||
// Usage
|
||||
var dog = Dog();
|
||||
dog.breathe(); // Inherited from Animal
|
||||
dog.walk(); // Inherited from Mammal
|
||||
dog.bark(); // Dog's own method
|
||||
```
|
||||
|
||||
In this example, `Dog` inherits from `Mammal`, which in turn inherits from `Animal`. This creates a hierarchy where `Dog` has access to all methods from its parent classes.
|
||||
|
||||
## 4. Polymorphism
|
||||
|
||||
Polymorphism allows objects of different classes to be treated as objects of a common superclass. It enables a single interface to represent different underlying forms (data types).
|
||||
|
||||
### Key Points:
|
||||
- In Dart, polymorphism is achieved through method overriding and interfaces.
|
||||
- The `@override` annotation is used to indicate that a method is intended to override a superclass method.
|
||||
|
||||
### Example:
|
||||
|
||||
```dart
|
||||
abstract class Shape {
|
||||
double calculateArea();
|
||||
}
|
||||
|
||||
class Rectangle extends Shape {
|
||||
double width;
|
||||
double height;
|
||||
|
||||
Rectangle(this.width, this.height);
|
||||
|
||||
@override
|
||||
double calculateArea() {
|
||||
return width * height;
|
||||
}
|
||||
}
|
||||
|
||||
class Circle extends Shape {
|
||||
double radius;
|
||||
|
||||
Circle(this.radius);
|
||||
|
||||
@override
|
||||
double calculateArea() {
|
||||
return 3.14 * radius * radius;
|
||||
}
|
||||
}
|
||||
|
||||
// Usage
|
||||
void printArea(Shape shape) {
|
||||
print('Area: ${shape.calculateArea()}');
|
||||
}
|
||||
|
||||
var rectangle = Rectangle(5, 3);
|
||||
var circle = Circle(2);
|
||||
|
||||
printArea(rectangle); // Output: Area: 15.0
|
||||
printArea(circle); // Output: Area: 12.56
|
||||
```
|
||||
|
||||
In this example, both `Rectangle` and `Circle` are treated as `Shape` objects. The `printArea()` function demonstrates polymorphism by working with any `Shape` object, regardless of its specific type.
|
||||
|
||||
## Conclusion
|
||||
|
||||
Understanding these four pillars of object-oriented programming is crucial for effective Dart and Flutter development. They provide a solid foundation for creating modular, maintainable, and scalable applications. Practice implementing these concepts in your projects to reinforce your understanding and improve your coding skills.
|
||||
Reference in New Issue
Block a user