Dart Class

Dart Классыг Ойлгох нь

Класс гэж юу вэ?

  • Объект үүсгэх загвар
  • Өгөгдөл ба үйлдлийг багцалдаг
  • ОХП-ын(Объект хандалтат Программчлал) үндсэн бүтээх блок

Үндсэн Классын Бүтэц


class Person {
    // Шинж чанарууд (instance хувьсагчид)
    String name;
    int age;

    // Байгуулагч
    Person(this.name, this.age);

    // Функц
    void introduce() {
        print('Сайн уу, Намайг $name гэдэг, би $age настай.');
    }
}
                

Dart Классыг Ойлгох нь

Зурагаас Объект хүртэл

Класс бол Архитектурын Зураг мэт

📝 Класс (Зураг)

Объект үүсгэх заавар

🏠 Объект (Байшин)

Компьютерийн санах ой дахь бодит өгөгдөл

Жишээ:

String класс нь бүтцийг тодорхойлно

'Hello, Dart!' нь бодит String объект юм

Классын Үндсэн Бүтэц


class User {
    // Properties (Шинж чанарууд)
    int id = 0;
    String name = '';

    // Method (Функц)
    void displayInfo() {
        print('ID: $id, Name: $name');
    }
}
                

Энэ жишээн дээр:

  • id, name нь class-ын шинж чанарууд
  • displayInfo() нь class-ын метод

Объект Үүсгэх


void main() {
    // Объект үүсгэх
    final user = User();

    // Утга оноох
    user.name = 'Bold';
    user.id = 42;

    // Метод дуудах
    user.displayInfo();
}
                

Dart 2.0-с хойш new түлхүүр үг заавал биш болсон

Properties ба Methods

Properties

Классын өгөгдлийг хадгалах хувьсагчид


class Car {
    String brand;
    String model;
    int year;
}
                        

Methods

Классын үйлдлүүдийг тодорхойлох функцууд


class Car {
    void start() {
        print('Engine started');
    }
}
                        

Private Members


class Password {
    // Private property
    String _plainText = 'pass123';

    // Getter
    String get password => _plainText;

    // Setter with validation
    set password(String value) {
        if (value.length < 6) {
            print('Password must be at least 6 characters!');
            return;
        }
        _plainText = value;
    }
}
                

Private гишүүдийг _ (underscore)-р эхэлж тодорхойлно

Cascade Notation (..)

Энгийн бичиглэл:


final user = User();
user.name = 'Bold';
user.id = 42;
                    

Cascade ашиглан:


final user = User()
  ..name = 'Bold'
  ..id = 42;
                    

Objects as References


class MyClass {
    int value = 1;
}

void main() {
    final obj1 = MyClass();
    final obj2 = obj1; // obj2 нь obj1-ийн reference

    obj2.value = 42;
    print(obj1.value); // 42 хэвлэнэ
    print(obj2.value); // 42 хэвлэнэ
}
                

Объектууд нь санах ой дахь reference утгаар дамжуулагддаг

Encapsulation

Өгөгдөл ба логикийг нуух зарчим


class BankAccount {
    double _balance = 0.0;

    double get balance => _balance;

    bool withdraw(double amount) {
        if (amount <= _balance) {
            _balance -= amount;
            return true;
        }
        return false;
    }
}
                    

toString() Method


class Person {
    String name;
    int age;

    Person(this.name, this.age);

    @override
    String toString() {
        return 'Person(name: $name, age: $age)';
    }
}

void main() {
    final person = Person('Bold', 25);
    print(person); // Person(name: Bold, age: 25)
}
                

Dart дээр Бүх зүйл Объект юм

  • Бүх утга нь классаас бүтсэн объектууд юм
  • Үүнд үндсэн төрлүүд орно:
    • int (бүхэл тоо)
    • double (бутархай тоо)
    • bool (логик утга)

Dart Классын Жишээ

String


final str = 'Hello, Dart!';
print(str.length); // 12
print(str.toUpperCase()); // HELLO, DART!
                        

List


final numbers = [1, 2, 3, 4, 5];
print(numbers.length); // 5
print(numbers.reversed); // [5, 4, 3, 2, 1]
                        

Dart Классын Жишээ

Map


final person = {
    'name': 'Bold',
    'age': 25
};
print(person['name']); // Bold
print(person['age']); // 25
                        

DateTime


final now = DateTime.now();
print(now.year); // 2021
print(now.month); // 6
                        

Dart Классын Жишээ

File


import 'dart:io';

final file = File('example.txt');
file.writeAsStringSync('Hello, Dart!');
                        

HttpClient


import 'dart:io';

final client = HttpClient();
final request = await client.getUrl(Uri.parse('https://example.com'));
final response = await request.close();
                        

Dart Классын Жишээ

Animal Class


class Animal {
    String name;
    int age;

    Animal(this.name, this.age);

    void speak() {
        print('Animal $name is speaking');

    }
}

void main() {
    final dog = Animal('Dog', 3);
    dog.speak(); // Animal Dog is speaking
}
                        

Dart Классын Жишээ

Calculator Class with Default Constructor

class Calculator {
    int add(int a, int b) {
        return a + b;
    }
    int subtract(int a, int b) {
        return a - b;
    }
    int multiply(int a, int b) {
        return a * b;
    }
    int divide(int a, int b) {
        return a ~/ b;
    }
}

void main() {
    final calc = Calculator();
    print(calc.add(10, 20)); // 30
}
                        

Dart Классын Жишээ

Calculator Class with Named Constructor

class Calculator {
    int add(int a, int b) {
        return a + b;
    }
    int subtract(int a, int b) {
        return a - b;
    }
    int multiply(int a, int b) {
        return a * b;
    }
    int divide(int a, int b) {
        return a ~/ b;
    }
    Calculator.fromJson(Map<String, <dynamic> json) { // Initialize properties from JSON }
}
void main() {
    final calc = Calculator.fromJson({'key': 'value'});
}
                        

Dart ба Java: Төрлийн Системүүд

Java

Анхдагч төрлүүдтэй

int x = 10;
// x нь анхдагч 10

Dart

Бүх зүйл объект

int x = 10;
// x нь Integer объект

ОХП дахь Классууд

Үндсэн Бүрэлдэхүүн

Классууд нэгтгэдэг:

  • Өгөгдөл (Шинж чанарууд)
  • Функцууд (Методууд)

Нэг цогц бүтэц болгон

Дүгнэлт

  • Классууд бол объектуудын загвар
  • Dart дээр бүх зүйл объект
  • Классууд нь өгөгдөл, функцуудыг нэгтгэдэг
  • Классууд нь ОХП-ын үндсэн хэсэг юм

Даалгавар #1

Дараах шинж чанартай Car класс үүсгэнэ үү:

  • Шинж чанарууд: brand, model, year
  • Байгуулагч
  • Функц: displayInfo()

Даалгавар #1


class Car {
    String brand;
    String model;
    int year;

    Car(this.brand, this.model, this.year);

    void displayInfo() {
        print('$year $brand $model');
    }
}
                    

Dart Class Constructors

Constructor төрлүүд:

  • Default constructor
  • Named constructor
  • Factory constructor
  • Constant constructor
  • Redirecting constructor

Constructors

Объект үүсгэх тусгай функц


class Person {
    String name;
    int age;

    // Энгийн constructor
    Person(this.name, this.age);

    // Named constructor
    Person.guest() {
        name = 'Guest';
        age = 18;
    }

    // Named constructor with initializer list
    Person.newBorn(): age = 0 {
        name = 'Baby';
    }
}
                    

Constructor-ын Төрлүүд

Default Constructor


class Point {
    int x, y;
    Point(this.x, this.y);
}
                        

Named Constructor


class Point {
    int x, y;
    Point.origin() {
        x = 0;
        y = 0;
    }
}
                        

Default Constructor


class Person {
    String name;
    int age;

    // Энгийн constructor
    Person(this.name, this.age);

    // Эсвэл
    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

void main() {
    var person = Person('Bold', 25);
    print('${person.name} is ${person.age} years old');
}
                

this.name гэж бичих нь илүү товч бөгөөд түгээмэл хэрэглэгддэг

Named Constructor


class Point {
    double x, y;

    // Default constructor
    Point(this.x, this.y);

    // Named constructor
    Point.origin() {
        x = 0;
        y = 0;
    }

    // Named constructor with parameters
    Point.fromList(List<double> coords) {
        if (coords.length != 2) {
            throw ArgumentError('Must have exactly 2 coordinates');
        }
        x = coords[0];
        y = coords[1];
    }

    @override
    String toString() => 'Point($x, $y)';
}

void main() {
    var p1 = Point(2, 3);
    var p2 = Point.origin();
    var p3 = Point.fromList([4, 5]);

    print(p1);  // Point(2, 3)
    print(p2);  // Point(0, 0)
    print(p3);  // Point(4, 5)
}
                

Initializer List


class Rectangle {
    final double width;
    final double height;
    final double area;

    // Initializer list-г : ашиглан бичнэ
    Rectangle(this.width, this.height) : area = width * height {
        if (width <= 0 || height <= 0) {
            throw ArgumentError('Dimensions must be positive');
        }
    }

    // Named constructor with initializer
    Rectangle.square(double size)
        : width = size,
          height = size,
          area = size * size;
}

void main() {
    var rect = Rectangle(3, 4);
    print('Area: ${rect.area}');  // Area: 12.0

    var square = Rectangle.square(5);
    print('Square area: ${square.area}');  // Square area: 25.0
}
                

Factory Constructor


class Database {
    static Database? _instance;
    String name;

    // Private constructor
    Database._internal(this.name);

    // Factory constructor
    factory Database(String name) {
        _instance ??= Database._internal(name);
        return _instance!;
    }
}

class Color {
    final int red;
    final int green;
    final int blue;

    // Private constructor
    Color._internal(this.red, this.green, this.blue);

    // Factory constructor
    factory Color.fromString(String colorString) {
        switch (colorString.toLowerCase()) {
            case 'red':
                return Color._internal(255, 0, 0);
            case 'green':
                return Color._internal(0, 255, 0);
            case 'blue':
                return Color._internal(0, 0, 255);
            default:
                throw ArgumentError('Invalid color string');
        }
    }
}

void main() {
    // Singleton pattern using factory
    var db1 = Database('MainDB');
    var db2 = Database('TestDB');
    print(identical(db1, db2));  // true

    // Creating objects based on input
    var color1 = Color.fromString('red');
    var color2 = Color.fromString('blue');
    print('Red value: ${color1.red}');  // 255
}
                

Factory Constructor


class Logger {
static final Map<String, Logger> _cache = {};
final String name;

factory Logger(String name) {
return _cache.putIfAbsent(
    name, () => Logger._internal(name));
}

Logger._internal(this.name);
}
            

Factory constructor нь шинэ instance үүсгэхгүйгээр байгаа instance-г буцааж болно

Constant Constructor


class ImmutablePoint {
    final double x;
    final double y;

    // Constant constructor
    const ImmutablePoint(this.x, this.y);

    @override
    String toString() => 'Point($x, $y)';
}

class Configuration {
    final String apiUrl;
    final int timeout;
    final bool debug;

    const Configuration({
        this.apiUrl = 'https://api.example.com',
        this.timeout = 30,
        this.debug = false
    });
}

void main() {
    // Same instance will be reused
    const p1 = ImmutablePoint(1, 1);
    const p2 = ImmutablePoint(1, 1);
    print(identical(p1, p2));  // true

    const config1 = Configuration();
    const config2 = Configuration(debug: true);
    print(config1.apiUrl);  // https://api.example.com
    print(config2.debug);   // true
}
                

Constant constructor нь compile time-д тогтмол утга үүсгэхэд ашиглагдана

Redirecting Constructor


class Animal {
    String name;
    int age;
    String type;

    // Main constructor
    Animal(this.name, this.age, this.type);

    // Redirecting constructors
    Animal.cat(String name, int age) : this(name, age, 'cat');
    Animal.dog(String name, int age) : this(name, age, 'dog');

    // Redirecting with default values
    Animal.kitten(String name) : this.cat(name, 1);
    Animal.puppy(String name) : this.dog(name, 1);
}

class Person {
    String firstName;
    String lastName;
    int age;

    // Main constructor
    Person(this.firstName, this.lastName, this.age);

    // Redirecting using named parameters
    Person.fromMap(Map<String, dynamic> map)
        : this(map['firstName'] as String,
              map['lastName'] as String,
              map['age'] as int);

    @override
    String toString() => '$firstName $lastName, $age years old';
}

void main() {
    var cat = Animal.kitten('Fluffy');
    print('${cat.name} is a ${cat.type}');  // Fluffy is a cat

    var person = Person.fromMap({
        'firstName': 'Bold',
        'lastName': 'Bat',
        'age': 25
    });
    print(person);  // Bold Bat, 25 years old
}
                

Нарийвчилсан Жишээ


class User {
    final String id;
    final String name;
    final String email;
    final DateTime createdAt;
    final Map<String, dynamic> preferences;

    // Private constructor
    User._internal(this.id, this.name, this.email,
        this.createdAt, this.preferences);

    // Named constructor with validation
    factory User.create({
        required String name,
        required String email,
        Map<String, dynamic>? preferences
    }) {
        // Validate email
        if (!email.contains('@')) {
            throw ArgumentError('Invalid email format');
        }

        return User._internal(
            DateTime.now().millisecondsSinceEpoch.toString(),
            name,
            email,
            DateTime.now(),
            preferences ?? {}
        );
    }

    // Create from JSON
    factory User.fromJson(Map<String, dynamic> json) {
        return User._internal(
            json['id'] as String,
            json['name'] as String,
            json['email'] as String,
            DateTime.parse(json['createdAt'] as String),
            json['preferences'] as Map<String, dynamic>
        );
    }

    // Convert to JSON
    MapMap<String, dynamic> toJson() {
        return {
            'id': id,
            'name': name,
            'email': email,
            'createdAt': createdAt.toIso8601String(),
            'preferences': preferences,
        };
    }

    @override
    String toString() => 'User(name: $name, email: $email)';
}

void main() {
    // Creating new user
    try {
        var user1 = User.create(
            name: 'Bold',
            email: 'bold@example.com',
            preferences: {'theme': 'dark', 'language': 'mn'}
        );
        print(user1);

        // Converting to JSON
        var json = user1.toJson();
        print('JSON: $json');

        // Creating from JSON
        var user2 = User.fromJson(json);
        print('Recreated user: $user2');

        // This will throw an error
        var invalidUser = User.create(
            name: 'Test',
            email: 'invalid-email'
        );
    } catch (e) {
        print('Error: $e');
    }
}
                

Дүгнэлт

Constructor төрлүүд:

  • Default: Энгийн constructor - ClassName(this.prop)
  • Named: Нэртэй constructor - ClassName.name()
  • Factory: Шинэ объект үүсгэхгүй байж болно - factory ClassName()
  • Const: Compile time-д тогтмол утга үүсгэнэ - const ClassName()
  • Redirecting: Өөр constructor дуудна - ClassName.name() : this()

Constructor сонголт:

  • Энгийн объект: Default constructor
  • Олон үүсгэх арга: Named constructor
  • Нэг instance: Factory constructor
  • Тогтмол утга: Const constructor
  • Давтагдсан код багасгах: Redirecting constructor

Class Extension буюу Өвлөлт

Өвлөлт нь класст байгаа properties, methods-г өөр класст өвлүүлж авах боломжийг олгодог

  • extends түлхүүр үг ашиглана
  • super түлхүүр үг ашиглан эцэг классын функцуудыг дуудна
  • @override decorator ашиглан функцуудыг дахин тодорхойлно

Class Extension


class Animal {
    String name;
    Animal(this.name);

    void makeSound() {
        print('Some sound');
    }
}

class Dog extends Animal {
    Dog(String name) : super(name);

    @override
    void makeSound() {
        print('Woof!');
    }
}
                

Энгийн Class Extension Жишээ

class Animal {
    String name;

    Animal(this.name);

    void makeSound() {
        print('Some generic sound');
    }

    void introduce() {
        print('I am $name');
    }
}

class Dog extends Animal {
    String breed;

    Dog(String name, this.breed) : super(name);

    @override
    void makeSound() {
        print('Woof! Woof!');
    }

    void showDetails() {
        introduce();  // Эцэг классын функцийг дуудаж байна
        print('I am a $breed dog');
        makeSound();  // Override хийсэн функцийг дуудаж байна
    }
}

void main() {
    var dog = Dog('Banhar', 'Mongolian Bankhar');
    dog.showDetails();
}
                        
// Гаралт: I am Banhar I am a Mongolian Bankhar dog Woof! Woof!

Нарийвчилсан Class Extension Жишээ

class Vehicle {
    String brand;
    int year;
    double _price;

    Vehicle(this.brand, this.year, this._price);

    double get price => _price;

    void startEngine() {
        print('Engine starting...');
    }

    double calculateValue() {
        int age = DateTime.now().year - year;
        return _price * (1 - age * 0.1);
    }
}

class Car extends Vehicle {
    int doors;
    String transmission;

    Car(String brand, int year, double price, this.doors, this.transmission)
        : super(brand, year, price);

    @override
    void startEngine() {
        super.startEngine();  // Эцэг классын функцийг дуудаж байна
        print('Car ready to drive!');
    }

    @override
    double calculateValue() {
        double baseValue = super.calculateValue();  // Эцэг классын тооцоолол
        // Transmission-с хамааруулж үнийг тооцоолох
        if (transmission == 'automatic') {
            return baseValue * 1.1;
        }
        return baseValue;
    }
}

void main() {
    var car = Car('Toyota', 2020, 30000, 4, 'automatic');
    car.startEngine();
    print('Current value: \$${car.calculateValue().toStringAsFixed(2)}');
}
                
// Гаралт: Engine starting... Car ready to drive! Current value: $26400.00

Extension Methods

Extension methods нь байгаа классуудад шинэ функц нэмэх боломжийг олгодог

  • Классын кодыг өөрчлөхгүйгээр шинэ функц нэмэх
  • Built-in классуудад (String, int, г.м) функц нэмэх
  • Бусад library-н классуудад функц нэмэх

Энгийн Extension Methods


extension StringHelper on String {
    bool isValidEmail() {
        return contains('@') && contains('.');
    }

    String capitalize() {
        if (isEmpty) return this;
        return '${this[0].toUpperCase()}${substring(1).toLowerCase()}';
    }

    String hideEmail() {
        if (!isValidEmail()) return this;
        var parts = split('@');
        return '${parts[0][0]}***@${parts[1]}';
    }
}

void main() {
    print('hello world'.capitalize());
    print('test@gmail.com'.isValidEmail());
    print('john.doe@gmail.com'.hideEmail());
}
                
// Гаралт: Hello world true j***@gmail.com

Нарийвчилсан Extension Methods


extension NumericHelper on num {
    Duration toMinutes() => Duration(minutes: toInt());
    Duration toHours() => Duration(hours: toInt());

    bool isBetween(num start, num end) {
        return this >= start && this <= end;
    }
}

extension ListHelper on List {
    T? secondOrNull() {
        return length >= 2 ? this[1] : null;
    }

    List takeFirstHalf() {
        return take((length / 2).ceil()).toList();
    }

    Map> groupBy(K Function(T) keyFunction) {
        Map> result = {};
        for (var item in this) {
            var key = keyFunction(item);
            (result[key] ??= []).add(item);
        }
        return result;
    }
}

void main() {
    // Numeric extensions
    print(5.toMinutes());
    print(2.5.isBetween(1, 3));

    // List extensions
    var numbers = [1, 2, 3, 4, 5, 6];
    print(numbers.secondOrNull());
    print(numbers.takeFirstHalf());

    var people = ['John', 'Jane', 'Bob', 'Alice'];
    var grouped = people.groupBy((name) => name[0]);
    print(grouped);
}
                
// Гаралт: 0:05:00.000000 true 2 [1, 2, 3] {J: [John, Jane], B: [Bob], A: [Alice]}

Number Extensions


extension NumberExtension on num {
    Duration toMinutes() => Duration(minutes: toInt());

    bool isBetween(num start, num end) {
        return this >= start && this <= end;
    }

    String toMoney() => '₮${toStringAsFixed(2)}';
}

void main() {
    print(5.toMinutes());              // 0:05:00.000000
    print(10.isBetween(5, 15));        // true
    print(1234.56.toMoney());          // ₮1234.56
}
                

List Extensions


extension ListExtension on List {
    T? firstOrNull() => isEmpty ? null : first;

    List takeFirstHalf() {
        return take((length / 2).ceil()).toList();
    }

    Map> groupBy(K Function(T) keySelector) {
        return fold({}, (map, element) {
            final key = keySelector(element);
            (map[key] ??= []).add(element);
            return map;
        });
    }
}

void main() {
    var numbers = [1, 2, 3, 4, 5];
    print(numbers.takeFirstHalf());     // [1, 2, 3]

    var people = ['John', 'Jane', 'Bob'];
    var grouped = people.groupBy((name) => name[0]);
    print(grouped);     // {J: [John, Jane], B: [Bob]}
}
                

Практик Жишээ


class Vehicle {
    String model;
    int year;

    Vehicle(this.model, this.year);

    void startEngine() => print('Engine starting...');
}

class ElectricCar extends Vehicle {
    int batteryLevel;

    ElectricCar(String model, int year, this.batteryLevel)
        : super(model, year);

    @override
    void startEngine() {
        if (batteryLevel < 10) {
            print('Low battery!');
            return;
        }
        print('Checking battery: $batteryLevel%');
        super.startEngine();
        print('Electric motor ready!');
    }
}

extension VehicleExtension on Vehicle {
    String getAge() {
        int age = DateTime.now().year - year;
        return '$model is $age years old';
    }
}

void main() {
    var tesla = ElectricCar('Model 3', 2022, 80);
    tesla.startEngine();
    print(tesla.getAge());
}
                

Чухал Анхаарах Зүйлс

Class Extension:

  • Private гишүүдэд хандах боломжгүй
  • Constructor-г override хийх боломжгүй
  • Олон удаа өвлөх боломжгүй

Extension Methods:

  • Instance variables зарлах боломжгүй
  • Constructor зарлах боломжгүй
  • Override decorator ашиглах боломжгүй

Сайн Дадлууд

Class Extension:

  • "is-a" харьцаатай классуудад ашиглах
  • Override хийсэн функцэд super дуудах
  • Өвлөлтийн гүн 2-3 түвшнээс хэтрүүлэхгүй байх

Extension Methods:

  • Тодорхой, ойлгомжтой нэр өгөх
  • Нэг зорилготой, энгийн функцууд бичих
  • Байгаа функцуудтай давхардуулахгүй байх

Чухал Зөвлөмжүүд

  1. Class нэр том үсгээр эхэлнэ
  2. Private member заавал ашиглах
  3. Getter/setter зөв хэрэглэх
  4. Хэт их өвлөлтөөс зайлсхийх
  5. Extension-г зөв хэрэглэх
  6. toString() override хийх
  7. Constructor сонголтыг зөв хийх

Private Members, Getters & Setters

  • Private members: _ (underscore)-р эхэлнэ
  • Getter: get түлхүүр үг ашиглана
  • Setter: set түлхүүр үг ашиглана

Энгийн Жишээ - BankAccount

class BankAccount {
    // Private properties
    double _balance = 0.0;
    String _accountNumber;
    List _transactions = [];

    BankAccount(this._accountNumber);

    // Simple getter
    double get balance => _balance;

    // Getter with formatting
    String get formattedBalance =>
        '₮${_balance.toStringAsFixed(2)}';

    // Getter that returns copy of private list
    List get transactions =>
        List.unmodifiable(_transactions);

    // Setter with validation
    void deposit(double amount) {
        if (amount <= 0) {
            throw ArgumentError('Amount must be positive');
        }
        _balance += amount;
        _transactions.add('Deposit: ₮$amount');
    }
}

void main() {
    var account = BankAccount('1234');
    account.deposit(1000);
    print(account.formattedBalance);
    print(account.transactions);
}
                
// Гаралт: ₮1000.00 [Deposit: ₮1000]

Private Members - Гүнзгий Ойлголт


// file: user.dart
class User {
    String _name;  // Private property
    int _age;      // Private property

    User(this._name, this._age);

    // Private method
    void _validateAge() {
        if (_age < 0) {
            throw Exception('Age cannot be negative');
        }
    }
}

// Өөр file-д хандах боломжгүй
// file: main.dart
void main() {
    final user = User('Bold', 25);
    // user._name;  // Error
    // user._validateAge();  // Error
}
                    

Getters and Setters

Basic Getter/Setter


class Rectangle {
    double _width;
    double _height;

    double get width => _width;
    double get height => _height;

    set width(double value) {
        if (value > 0) _width = value;
    }
}
                        

Computed Property


class Rectangle {
    double _width;
    double _height;

    double get area => _width * _height;

    double get perimeter =>
        2 * (_width + _height);
}
                        

Getter/Setter - Нарийвчилсан Жишээ


class Temperature {
    double _celsius;

    Temperature(this._celsius);

    // Getter for Celsius
    double get celsius => _celsius;

    // Getter for Fahrenheit
    double get fahrenheit => _celsius * 9/5 + 32;

    // Setter with validation
    set celsius(double value) {
        if (value < -273.15) {
            throw Exception('Temperature below absolute zero!');
        }
        _celsius = value;
    }

    // Setter for Fahrenheit
    set fahrenheit(double value) {
        celsius = (value - 32) * 5/9;
    }
}
                

Нарийвчилсан Жишээ - ShoppingCart


class ShoppingCart {
    // Private properties
    final List> _items = [];
    double _discount = 0.0;
    bool _isVIP = false;

    // Computed getter for total
    double get total {
        double sum = _items.fold(0,
            (sum, item) => sum + (item['price'] * item['quantity']));
        return sum * (1 - _discount);
    }

    // Getter with formatting
    String get receipt {
        var buffer = StringBuffer();
        buffer.writeln('=== Receipt ===');
        for (var item in _items) {
            buffer.writeln(
                '${item['name']} x${item['quantity']}: ₮${item['price']}');
        }
        if (_discount > 0) {
            buffer.writeln('Discount: ${(_discount * 100).toStringAsFixed(0)}%');
        }
        buffer.writeln('Total: ₮${total.toStringAsFixed(2)}');
        return buffer.toString();
    }

    // Setter with validation
    set discount(double value) {
        if (value < 0 || value > 1) {
            throw ArgumentError('Discount must be between 0 and 1');
        }
        _discount = value;
    }

    // Private method
    void _validateItem(String name, double price, int quantity) {
        if (name.isEmpty) throw ArgumentError('Name cannot be empty');
        if (price <= 0) throw ArgumentError('Price must be positive');
        if (quantity <= 0) throw ArgumentError('Quantity must be positive');
    }

    // Public method using private properties
    void addItem(String name, double price, int quantity) {
        _validateItem(name, price, quantity);
        _items.add({
            'name': name,
            'price': price,
            'quantity': quantity
        });
    }
}

void main() {
    var cart = ShoppingCart();
    cart.addItem('Laptop', 1200000, 1);
    cart.addItem('Mouse', 50000, 2);
    cart.discount = 0.1; // 10% discount
    print(cart.receipt);
    print('Total to pay: ₮${cart.total}');
}
                
=== Receipt === Laptop x1: ₮1200000 Mouse x2: ₮50000 Discount: 10% Total: ₮1170000.00

Өргөтгөсөн Жишээ - UserProfile


class UserProfile {
    // Private properties
    String _firstName;
    String _lastName;
    DateTime _birthDate;
    List _roles = [];
    Map _settings = {};

    UserProfile(this._firstName, this._lastName, this._birthDate);

    // Computed getters
    String get fullName => '$_firstName $_lastName';

    int get age {
        final today = DateTime.now();
        var age = today.year - _birthDate.year;
        if (today.month < _birthDate.month ||
            (today.month == _birthDate.month &&
             today.day < _birthDate.day)) {
            age--;
        }
        return age;
    }

    bool get isAdult => age >= 18;

    // List getter with validation
    List get roles {
        if (_roles.isEmpty) return ['user'];
        return List.unmodifiable(_roles);
    }

    // Map getter
    Map get settings =>
        Map.unmodifiable(_settings);

    // Setters with validation
    set firstName(String value) {
        if (value.isEmpty) {
            throw ArgumentError('First name cannot be empty');
        }
        _firstName = value.trim();
    }

    set lastName(String value) {
        if (value.isEmpty) {
            throw ArgumentError('Last name cannot be empty');
        }
        _lastName = value.trim();
    }

    // Complex setter
    set birthDate(DateTime value) {
        final today = DateTime.now();
        if (value.isAfter(today)) {
            throw ArgumentError('Birth date cannot be in the future');
        }
        if (today.year - value.year > 120) {
            throw ArgumentError('Invalid birth date');
        }
        _birthDate = value;
    }

    // Method to update settings
    void updateSetting(String key, dynamic value) {
        // Validate setting key
        if (!['theme', 'language', 'notifications'].contains(key)) {
            throw ArgumentError('Invalid setting key');
        }
        _settings[key] = value;
    }

    // Method to add role with validation
    void addRole(String role) {
        role = role.toLowerCase();
        if (!['admin', 'moderator', 'user'].contains(role)) {
            throw ArgumentError('Invalid role');
        }
        if (!_roles.contains(role)) {
            _roles.add(role);
        }
    }

    // Complex getter for user summary
    String get summary {
        var buffer = StringBuffer();
        buffer.writeln('User Profile:');
        buffer.writeln('Name: $fullName');
        buffer.writeln('Age: $age (${isAdult ? 'Adult' : 'Minor'})');
        buffer.writeln('Roles: ${roles.join(', ')}');
        buffer.writeln('Settings: ');
        _settings.forEach((key, value) =>
            buffer.writeln('  $key: $value'));
        return buffer.toString();
    }
}

void main() {
    var user = UserProfile(
        'Bold',
        'Bat',
        DateTime(2000, 5, 15)
    );

    user.addRole('admin');
    user.updateSetting('theme', 'dark');
    user.updateSetting('language', 'mn');

    print(user.summary);
}
                
User Profile: Name: Bold Bat Age: 23 (Adult) Roles: admin Settings: theme: dark language: mn

Library System Жишээ


class Library {
    // Private properties
    final Map _books = {};
    final Set _members = {};
    final Map> _borrowedBooks = {};

    // Getters for statistics
    int get totalBooks => _books.length;
    int get availableBooks => _books.values
        .where((book) => !book.isBorrowed).length;
    int get totalMembers => _members.length;

    // Getter for borrowed books report
    String get borrowedBooksReport {
        var buffer = StringBuffer();
        buffer.writeln('Borrowed Books Report:');
        _borrowedBooks.forEach((member, books) {
            buffer.writeln('$member: ${books.length} books');
            for (var bookId in books) {
                var book = _books[bookId];
                if (book != null) {
                    buffer.writeln('  - ${book.title}');
                }
            }
        });
        return buffer.toString();
    }

    // Private validation methods
    void _validateMember(String memberId) {
        if (!_members.contains(memberId)) {
            throw ArgumentError('Invalid member ID');
        }
    }

    void _validateBook(String bookId) {
        if (!_books.containsKey(bookId)) {
            throw ArgumentError('Invalid book ID');
        }
    }

    // Public methods
    void addBook(Book book) {
        _books[book.id] = book;
    }

    void registerMember(String memberId) {
        if (_members.contains(memberId)) {
            throw ArgumentError('Member already exists');
        }
        _members.add(memberId);
        _borrowedBooks[memberId] = [];
    }

    void borrowBook(String memberId, String bookId) {
        _validateMember(memberId);
        _validateBook(bookId);

        var book = _books[bookId]!;
        if (book.isBorrowed) {
            throw StateError('Book is already borrowed');
        }

        book.isBorrowed = true;
        _borrowedBooks[memberId]!.add(bookId);
    }
}

class Book {
    final String id;
    final String title;
    bool isBorrowed = false;

    Book(this.id, this.title);
}

void main() {
    var library = Library();

    // Add books
    library.addBook(Book('B1', 'The Great Gatsby'));
    library.addBook(Book('B2', '1984'));

    // Register member
    library.registerMember('M001');

    // Borrow book
    library.borrowBook('M001', 'B1');

    print('Total books: ${library.totalBooks}');
    print('Available books: ${library.availableBooks}');
    print(library.borrowedBooksReport);
}
                
Total books: 2 Available books: 1 Borrowed Books Report: M001: 1 books - The Great Gatsby

Дүгнэлт

Private Members:

  • Дотоод өгөгдлийг хамгаалах
  • Зөвхөн класс дотроос хандах боломжтой
  • Underscore (_) ашиглан тодорхойлно

Getters:

  • Өгөгдөлд хандах
  • Тооцоолол хийх
  • Форматлах

Setters:

  • Өгөгдөл шалгах
  • Алдааг боловсруулах
  • Өгөгдлийн бүрэн бүтэн байдлыг хангах

Dart Classes - Хураангуй

Класс бүрдэл хэсгүүд:

  • Properties: Class-ын шинж чанарууд
    • Public: String name;
    • Private: String _name;
  • Constructor: Объект үүсгэх функц
    • Default: ClassName(this.prop)
    • Named: ClassName.name()
    • Factory: factory ClassName()
  • Methods: Class-ын функцууд
    • Public: void display()
    • Private: void _process()
  • Getters/Setters: Утга авах, оноох
    • Getter: int get age => _age;
    • Setter: set age(int value)
  • Extension: Өргөтгөх
    • Class Extension: extends
    • Extension Methods: extension on Type

Сайн дадлууд:

  • Private гишүүдэд getter/setter ашиглах
  • Override функцүүдэд @override decorator хэрэглэх
  • Класс бүр нэг үүрэгтэй байх
  • toString() функцийг тодорхойлох
  • Өвлөлтийг зөв зорилгоор ашиглах

Чухал санамж:

  • Класс нэр том үсгээр эхэлнэ
  • Private гишүүд _ -ээр эхэлнэ
  • Функц нэр жижиг үсгээр эхэлнэ
  • Constant утгууд UPPERCASE_WITH_UNDERSCORES
  • Файл нэр snake_case.dart хэлбэртэй байна