Məzmuna keçin
  • Kateqoriyalar
  • Ən yeni
  • Teqlər
  • Populyar
Yığmaq
Brend loqosu
codexC

codex

@codex
Haqqında
Yazı
76
Mövzu
64
Paylaşımlar
0
Qruplar
1
İzləyicilər
1
İzləyir
0

Yazı

Ən yeni

  • TypeScript-də Generics
    codexC codex

    Generics — TypeScript-də məlumatların tipini dinamik şəkildə müəyyən etmək üçün istifadə olunan bir vasitədir. Generics proqramlarımızı yenidən istifadə edilə bilən və tip təhlükəsizliyi təmin edən şəkildə yazmağımıza kömək edir.

    Bu konsept bizə funksiyalarda, interfeyslərdə, classlarda və tiplərdə konkret tip əvəzinə gələcəkdə təyin ediləcək tip dəyişəni (T, U, K, s.) istifadə etməyə imkan verir.


    💡 Niyə Generics istifadə olunur?

    Əgər bir funksiyanı müxtəlif tiplərlə işləyəcək şəkildə yazmaq istəyiriksə və həmçinin TypeScript-in tip yoxlamasından faydalanmaq istəyiriksə, Generics çox faydalıdır.


    🔹 Sadə Generics nümunəsi

    function identity<T>(value: T): T {
      return value;
    }
    
    const str = identity<string>("Hello");
    const num = identity<number>(42);
    

    Bu nümunədə identity funksiyası hər hansı tipdə (T) dəyər alır və onu geri qaytarır. Bu funksiyanı həm string, həm number, həm də başqa istənilən tiplərlə istifadə etmək olar.


    🔸 Generics ilə Array işlənməsi

    function getFirstElement<T>(arr: T[]): T {
      return arr[0];
    }
    
    const first = getFirstElement<string>(["apple", "banana"]);
    const firstNum = getFirstElement<number>([10, 20, 30]);
    

    Burada T[] generik array-dir. Hansı tipdə array versəniz, TypeScript həmin tipdə cavab qaytaracaq.


    🔹 Generics ilə Interface və Type-lar

    interface Box<T> {
      content: T;
    }
    
    const stringBox: Box<string> = { content: "salam" };
    const numberBox: Box<number> = { content: 123 };
    

    Burada Box<T> interfeysi istənilən tipdə məlumat saxlamaq üçün generik olaraq təyin olunub.


    🔹 Generics ilə Class

    class Container<T> {
      private value: T;
    
      constructor(val: T) {
        this.value = val;
      }
    
      getValue(): T {
        return this.value;
      }
    }
    
    const container = new Container<string>("Data");
    console.log(container.getValue()); // "Data"
    

    Bu nümunədə Container class-ı generikdir və istənilən tipdə məlumat saxlaya bilir.


    🔸 Bir neçə tip dəyişəni ilə Generics

    function merge<T, U>(obj1: T, obj2: U): T & U {
      return { ...obj1, ...obj2 };
    }
    
    const merged = merge({ name: "Ali" }, { age: 25 });
    // merged: { name: "Ali", age: 25 }
    

    merge funksiyası iki fərqli tip qəbul edir və onların birləşməsini qaytarır.


    🔹 Tip məhdudiyyətləri (Constraints)

    Bəzən generik tipin müəyyən xüsusiyyətləri olmasını istəyə bilərik. Bu zaman extends istifadə olunur:

    function logLength<T extends { length: number }>(value: T): void {
      console.log(value.length);
    }
    
    logLength("Salam"); // 5
    logLength([1, 2, 3]); // 3
    

    Bu nümunədə T tipi yalnız length xüsusiyyətinə sahib olan tiplərlə məhdudlaşdırılıb.


    🔹 keyof Operatoru

    keyof operatoru bir obyektin açarlarını (key) tip kimi əldə etməyə imkan verir.

    interface Person {
      name: string;
      age: number;
    }
    
    type PersonKeys = keyof Person; // "name" | "age"
    

    Bu, xüsusilə dinamik açarlarla işləyərkən faydalıdır:

    function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
      return obj[key];
    }
    
    const person = { name: "Ali", age: 30 };
    const name = getProperty(person, "name"); // "Ali"
    

    🔹 infer və Conditional Types

    Conditional types tip əsaslı şərti ifadələr yaratmağa imkan verir. infer isə bu şərtlər daxilində tip çıxarmağa (inference) kömək edir.

    infer ilə tip çıxarma

    type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any;
    
    type Num = ReturnType<() => number>; // number
    type Str = ReturnType<(x: string) => string>; // string
    

    Burada infer R funksiyanın dönüş tipini çıxarır.

    Flatten nümunəsi

    type Flatten<T> = T extends Array<infer U> ? U : T;
    
    type Str = Flatten<string[]>; // string
    type Num = Flatten<number>;   // number
    

    Əgər T array tipidirsə, onun element tipini çıxarır, əks halda T-ni olduğu kimi saxlayır.


    🔹 Default Generic parametrlər

    Generik parametrlər üçün default (susmaya görə) dəyərlər təyin etmək mümkündür:

    function createArray<T = number>(length: number, value: T): T[] {
      return new Array(length).fill(value);
    }
    
    const numberArray = createArray(3, 0); // [0, 0, 0]
    const stringArray = createArray<string>(3, "hello"); // ["hello", "hello", "hello"]
    

    Burada T üçün default olaraq number tipi təyin edilib.


    ✅ Generics-in Üstünlükləri

    Üstünlük İzah
    🔁 Yenidən istifadə Eyni funksiya və ya sinif müxtəlif tiplərlə işləyə bilir.
    🔐 Tip təhlükəsizliyi Giriş və çıxış tipləri dəqiq müəyyənləşir.
    📦 Daha az təkrar kod Eyni əməliyyatı fərqli tiplərlə etmək üçün ayrıca funksiyalara ehtiyac yoxdur.

    📌 Nəticə

    Generics TypeScript-də çox güclü bir vasitədir və proqramların daha elastik, tip təhlükəsiz və yenidən istifadə oluna bilən olmasını təmin edir.

    Əgər siz funksiyalarınızın və strukturlarınızın tiplərini gələcəkdə təyin etmək istəyirsinizsə və təkrarı azaltmaq istəyirsinizsə — Generics istifadə etməyiniz tövsiyə olunur.

    TypeScript typescript generics

  • TypeScript-də type və interface
    codexC codex

    TypeScript statik tip təyin etmə imkanı verən JavaScript üzərində genişlənmiş bir proqramlaşdırma dilidir. Bu dildə məlumat strukturlarını daha aydın və təhlükəsiz şəkildə təsvir etmək üçün iki əsas vasitə var: type və interface.

    Bunların hər ikisi obyektlərin və verilən strukturlarının formasını təsvir etmək üçün istifadə olunur. Ancaq aralarında bəzi fərqli imkanlar və istifadə məqsədləri mövcuddur.


    🔹 interface nədir?

    interface – Obyektlərin strukturunu müəyyən etmək üçün istifadə olunur. Bir obyekt hansı sahələrə (fields) malik olacaq, onların tipi nə olacaq və hansılar məcburidir – bunlar interfeyslə müəyyənləşdirilir.

    Nümunə:

    interface Person {
      name: string;
      age: number;
      isStudent?: boolean; // optional field
    }
    

    Burada Person adlı interfeys name, age və istəyə bağlı isStudent sahələrini müəyyən edir.


    🔹 type nədir?

    type daha geniş imkanlara malikdir. O, həm obyektləri, həm də primitiv tipləri, birlik tipləri (union types), kəsişmə tipləri (intersection types) və tuple-ları təsvir edə bilər.

    Nümunə:

    type Person = {
      name: string;
      age: number;
    };
    

    Bu da interface-ə bənzər bir strukturdur, lakin type ilə aşağıdakıları da edə bilərik:

    Union Type (bir neçə növdən biri):

    type Status = "success" | "error" | "loading";
    

    Intersection Type (birləşmiş struktur):

    type Address = {
      city: string;
    };
    
    type Employee = Person & Address;
    

    ✅ Ortalıq Oxşarlıqları

    İmkan type interface
    Obyekt strukturu yaratmaq ✅ ✅
    Miras alma (inheritance) ✅ ✅
    Union və intersection yaratmaq ✅ ❌
    Tuple və primitive növləri müəyyənləşdirmək ✅ ❌
    Yenidən açılıb sahə əlavə etmək ❌ ✅ (Declaration merging)

    🔸 interface və type fərqləri

    Fərq type interface
    Quraşdırılmış genişlənmə type & operatoru ilə genişlənir interface birbaşa extends ilə genişlənə bilər
    Union, Intersection Tam dəstəklənir Dəstəklənmir
    Declaration merging (təkrar elan etmə) Olmaz Olur
    Primitiv tipləri təyin etmək Mümkündür (type Age = number) Mümkün deyil

    🔹 Hansını nə vaxt istifadə etməli?

    • Sadəcə obyekt strukturu təsvir edirsinizsə, interface istifadə etmək tövsiyə olunur.
    • Əgər union, intersection, primitiv və ya tuple növləri ilə işləyirsinizsə, type daha uyğun olar.
    • Üçüncü tərəf kitabxanalarında (React, Express) tez-tez interface istifadə olunur.

    ✅ Real dünya nümunəsi

    interface User {
      id: number;
      name: string;
    }
    
    type Role = "admin" | "user" | "guest";
    
    type UserWithRole = User & {
      role: Role;
    };
    

    Burada həm interface, həm də type birlikdə istifadə olunub.


    📌 Nəticə

    TypeScript-də type və interface hər ikisi strukturların və məlumatların təhlükəsiz işlənməsi üçün çox faydalıdır. Onların düzgün seçilməsi kodun daha oxunaqlı, yenidən istifadə oluna bilən və davamlı olmasını təmin edir.

    Əgər sadə obyekt strukturu ilə işləyirsinizsə – interface, daha kompleks tip təriflərinə ehtiyac varsa – type istifadə edin.

    TypeScript types interfaces typescript

  • Oracle SQL-də agregat funksiyalar
    codexC codex

    Agregat funksiyalar, Oracle SQL-də bir və ya bir neçə sətirdən ibarət məlumatları analiz etmək və ümumi nəticə çıxarmaq üçün istifadə olunur. Bu funksiyalar cədvəllərdəki dəyərləri qruplaşdırmaq, hesablamaq və filtrasiya etmək imkanı verir.

    Aşağıdakı ən çox istifadə olunan agregat funksiyalarla tanış olaq:

    İlk öncə misalları rahat göstərmək üçün employees adından cədvəl yaradaq və məlumatları ora əlavə edək

    EMPLOYEE_ID NAME SALARY DEPARTMENT_ID
    1 John Smith 3500 10
    2 Jane Doe 1600 10
    3 Emily Davis 2000 20
    4 Michael Brown 2500 30
    CREATE TABLE employees (
        employee_id NUMBER PRIMARY KEY,
        name VARCHAR2(100),
        salary NUMBER,
        department_id NUMBER
    );
    
    INSERT INTO employees (employee_id, name, salary, department_id)
    VALUES 
        (1, 'John Smith', 3500, 10),
        (2, 'Jane Doe', 1600, NULL),
        (3, 'Emily Davis', 2000, 20),
        (4, 'Michael Brown', 2500, 30);
    

    🔹 COUNT() – Sətirlərin sayını hesablayır

    Bu funksiya müəyyən bir sütundakı və ya bütün cədvəldəki sətirlərin sayını verir.

    Sintaksis:

    SELECT COUNT(*) FROM employees; --4
    

    Bütün işçilərin sayını qaytarır.

    Sütun səviyyəsində:

    SELECT COUNT(department_id) FROM employees; --3
    

    NULL olmayan department_id sütunlarının sayını qaytarır.


    🔹 SUM() – Toplam hesablayır

    Bu funksiya ədədi dəyərləri toplayır.

    SELECT SUM(salary) FROM employees; --9600
    

    Bütün işçilərin ümumi maaşını qaytarır.


    🔹 AVG() – Orta dəyəri hesablayır

    Bu funksiya ədədi sütun üzrə orta (average) dəyəri verir.

    SELECT AVG(salary) FROM employees; --2400
    

    Bütün işçilərin orta maaşını göstərir.


    🔹 MIN() – Ən kiçik dəyəri tapır

    Ən aşağı ədədi və ya əlifba sıralamasına görə minimum dəyəri qaytarır.

    SELECT MIN(salary) FROM employees; --1600
    

    Ən az maaşı olan işçinin maaşını qaytarır.

    SELECT MIN(name) FROM employees; --Emily Davis
    

    Əlifba sırasına görə ilk gələn adı göstərir.


    🔹 MAX() – Ən böyük dəyəri tapır

    Ən yüksək dəyəri qaytarır.

    SELECT MAX(salary) FROM employees; --3500
    

    Ən yüksək maaşı göstərir.


    🔸 GROUP BY ilə agregat funksiyalar

    Agregat funksiyaları GROUP BY ilə birlikdə istifadə edərək məlumatları qruplar üzrə analiz etmək mümkündür.

    SELECT department_id, AVG(salary)
    FROM employees
    GROUP BY department_id;
    

    Hər şöbə üçün orta maaş göstərilir.


    🔸 HAVING ilə agregat filtr

    Agregat nəticələri filtrasiya etmək üçün HAVING istifadə olunur. WHERE fərdi sətirlər üçün, HAVING isə GROUP BY nəticələri üçün tətbiq edilir.

    SELECT department_id, COUNT(*)
    FROM employees
    GROUP BY department_id
    HAVING COUNT(*) > 5;
    

    Yalnız 5-dən çox işçisi olan şöbələri göstərir.


    📌 Nəticə

    Oracle SQL-də agregat funksiyalar məlumatların xülasəsini çıxarmaq, ümumi mənzərəni görmək və qruplar üzrə analiz aparmaq üçün çox faydalıdır. GROUP BY, HAVING kimi əmr və funksiyalarla birlikdə istifadə olunduqda, çox güclü hesabatlar və analizlər aparmaq mümkündür.

    Oracle oracle sql aggregate avg sum

  • Oracle SQL-də JOIN əməliyyatları (Birləşdirmələr)
    codexC codex

    Verilənlər bazasında məlumatlar adətən normalizasiya edilmiş, yəni müxtəlif cədvəllərdə saxlanılır. Bu cədvəlləri əlaqələndirmək üçün JOIN əməliyyatlarından istifadə olunur. Oracle SQL-də bir neçə növ JOIN mövcuddur və hər biri fərqli ehtiyaclara cavab verir.


    🔗 1. INNER JOIN – Daxili birləşdirmə

    INNER JOIN iki və ya daha çox cədvəldə yalnız uyğun gələn (ortaq açar dəyəri olan) sətirləri birləşdirir. Nəzəri olaraq, inner join SQL sorğusu iki cədvəl arasında müqayisə edilən sətrlərin hamısının eyni dəyərlərə malik olması tələb olunur. Nəticədə, yalnız uyğunluq olan sətrləri nəticəyə əlavə edir.

    image (1).jpg

    Nümunə üçün iki cədvəli düşünək:

    Cədvəl 1: sifarişlər (orders)

    order_id customer_id goods_name order_date
    101 1 Laptop 2024-05-01
    102 1 Telefon 2024-05-03
    103 2 Tablet 2024-05-02
    104 3 Kamera 2024-05-04
    105 3 Klaviatura 2024-05-05

    Cədvəl 2: müştərilər (customers)

    customer_id name surname
    1 Ali Məmmədov
    2 Nigar Əliyeva
    3 Cavid Məmmədli

    Bu iki cədvəli birləşdirmək üçün aşağıdakı SQL sorğusunu istifadə edə bilərik:

    SELECT customers.name, customers.surname, orders.goods_name, orders.order_date
    FROM orders
    INNER JOIN customers ON customers.customer_id = orders.customer_id;
    

    Bu sorğunun nəticəsi belə olacaq:

    name surname goods_name order_date
    Ali Məmmədov Laptop 2024-05-01
    Ali Məmmədov Telefon 2024-05-03
    Nigar Əliyeva Tablet 2024-05-02
    Cavid Məmmədli Kamera 2024-05-04
    Cavid Məmmədli Klaviatura 2024-05-05

    Bu sorğu “müştərilər” və “sifarişlər” cədvəllərini customer_id sütunu əsasında birləşdirir. Nəticədə, hər bir sifarişin hansı müştəri tərəfindən verildiyi və sifariş tarixi ilə birlikdə müştəri adını və soyadını göstərir.

    -- müştərilərilər cədvəlinin yaradılması              
    CREATE TABLE customers (
        customer_id NUMBER PRIMARY KEY,
        name VARCHAR2(50),
        surname VARCHAR2(50)
    );
    
    -- müştərilər cədvəlinin doldurulması
    INSERT INTO customers (customer_id, name, surname) VALUES
    (1, 'Ali', 'Məmmədov'),
    (2, 'Nigar', 'Əliyeva'),
    (3, 'Cavid', 'Məmmədli');
    
    -- sifarişlər cədvəlinin yaradılması
    CREATE TABLE orders (
        order_id NUMBER PRIMARY KEY,
        customer_id NUMBER,
        goods_name VARCHAR2(100),
        order_date DATE,
        FOREIGN KEY (customer_id) REFERENCES customers(customer_id)
    );
    
    -- sifarişlər cədvəlinin doldurulması
    INSERT INTO orders (order_id, customer_id, goods_name, order_date) VALUES
    (101, 1, 'Laptop', DATE '2024-05-01'),
    (102, 1, 'Telefon', DATE '2024-05-03'),
    (103, 2, 'Tablet', DATE '2024-05-02'),
    (104, 3, 'Kamera', DATE '2024-05-04'),
    (105, 3, 'Klaviatura', DATE '2024-05-05');
    


    🔍 2. LEFT JOIN – Sol birləşdirmə

    LEFT JOIN sol cədvəldəki bütün sətirləri, sağ cədvəldə isə yalnız uyğun gələnləri birləşdirir. Əgər sağ tərəfdə uyğun sətir yoxdursa, həmin sütunlarda NULL göstərilir.

    image.jpg

    İki cədvəl nümunəsi:

    employees cədvəli:

    employee_id name department_id
    1 John Smith 10
    2 Jane Doe NULL
    3 Emily Davis 20
    4 Michael Brown 30

    departments cədvəli:

    department_id department_name
    10 IT
    20 HR
    30 Finance
    SELECT employees.employee_id, employees.name, departments.department_name
    FROM employees
    LEFT JOIN departments
    ON employees.department_id = departments.department_id;
    

    Bu sorğunun nəticəsi belə olacaq:

    employee_id name department_name
    1 John Smith IT
    2 Jane Doe NULL
    3 Emily Davis HR
    4 Michael Brown Finance

    CREATE TABLE departments (
        department_id NUMBER PRIMARY KEY,
        department_name VARCHAR2(100)
    );
    
    INSERT INTO departments (department_id, department_name)
    VALUES 
        (10, 'IT'),
        (20, 'HR'),
        (30, 'Finance');
    
    
    CREATE TABLE employees (
        employee_id NUMBER PRIMARY KEY,
        name VARCHAR2(100),
        department_id NUMBER,
        FOREIGN KEY (department_id) REFERENCES departments(department_id)
    );
    
    INSERT INTO employees (employee_id, name, department_id)
    VALUES 
        (1, 'John Smith', 10),
        (2, 'Jane Doe', NULL),
        (3, 'Emily Davis', 20),
        (4, 'Michael Brown', 30);
    


    🔎 3. RIGHT JOIN – Sağ birləşdirmə

    RIGHT JOIN sağ cədvəldəki bütün sətirləri, sol cədvəldə isə uyğun gələnləri birləşdirir. Əgər sol cədvəldə uyğun gələn sətir yoxdursa, onda nəticə dəstində sol cədvəldəki sütunlar üçün NULL dəyərləri olacaq.

    e602b870-cd54-4536-a665-283a9b565074-image.png

    Bir nümunə ilə izah edək. İki cədvəlimiz var:

    • Orders (Sifarişlər)
    • Customers (Müştərilər)

    Orders cədvəli:

    OrderID CustomerID OrderDate
    1 1001 2023-01-15
    2 1002 2023-02-20
    3 1003 2023-03-12

    Customers cədvəli:

    CustomerID CustomerName
    1001 Ali
    1002 Ayşe
    1004 Mehmet

    RIGHT JOIN sorğusu ilə Orders və Customers cədvəllərini birləşdirək:

    SELECT Orders.OrderID, Orders.OrderDate, Customers.CustomerName
    FROM Orders
    RIGHT JOIN Customers ON Orders.CustomerID = Customers.CustomerID;
    

    Bu sorğunun nəticəsi belə olacaq:

    OrderID OrderDate CustomerName
    1 2023-01-15 Ali
    2 2023-02-20 Ayşe
    NULL NULL Mehmet

    Göründüyü kimi, Customers cədvəlindəki bütün müştərilər nəticədə göstərilir, hətta Orders
    cədvəlində uyğun gələn sifariş olmadıqda belə. Mehmet üçün sifariş məlumatı olmadığından, onun üçün
    NULL dəyərləri qaytarılır.

    CREATE TABLE customers (
        CustomerID NUMBER PRIMARY KEY,
        CustomerName VARCHAR2(100)
    );
    
    INSERT INTO customers (CustomerID, CustomerName)
    VALUES 
        (1001, 'Ali'),
        (1002, 'Ayşe'),
        (1004, 'Mehmet');
    
    CREATE TABLE orders (
        OrderID NUMBER PRIMARY KEY,
        CustomerID NUMBER,
        OrderDate DATE
    );
    
    INSERT INTO orders (OrderID, CustomerID, OrderDate)
    VALUES 
        (1, 1001, TO_DATE('2023-01-15', 'YYYY-MM-DD')),
        (2, 1002, TO_DATE('2023-02-20', 'YYYY-MM-DD')),
        (3, 1003, TO_DATE('2023-03-12', 'YYYY-MM-DD'));
    


    🔄 4. FULL OUTER JOIN – Tam birləşdirmə

    Bu JOIN həm sol, həm də sağ cədvəldəki bütün sətirləri qaytarır. Uyğun gəlməyənlər üçün NULL istifadə olunur.

    Nümunə:

    SELECT employees.name, departments.name
    FROM employees
    FULL OUTER JOIN departments
    ON employees.dept_id = departments.id;
    

    🔁 5. CROSS JOIN – Çarpaz birləşdirmə

    CROSS JOIN hər bir sətiri digər cədvəldəki bütün sətirlərlə birləşdirir. Bu zaman kartesian hasil yaranır.

    Nümunə:

    SELECT A.name, B.name
    FROM tableA A
    CROSS JOIN tableB B;
    

    Əgər tableA 3 sətir, tableB 2 sətirdirsə, nəticə 6 sətirdən ibarət olacaq (3 × 2).


    💡 Alternativ JOIN Sintaksisi

    Oracle-da daha əvvəlki dövrlərdə istifadə olunan sintaksis belə idi:

    SELECT e.name, d.name
    FROM employees e, departments d
    WHERE e.dept_id = d.id;
    

    Bu yazılış INNER JOIN-in qısa formasıdır. Amma müasir SQL-də açıq şəkildə JOIN yazmaq daha oxunaqlı və texniki cəhətdən üstün sayılır.


    ✅ Nəticə

    JOIN Növü İzahı
    INNER JOIN Hər iki cədvəldə uyğun olan sətirləri qaytarır
    LEFT JOIN Sol cədvəldə olan bütün sətirləri, uyğun olanları sağdan
    RIGHT JOIN Sağ cədvəldə olan bütün sətirləri, uyğun olanları soldan
    FULL OUTER JOIN Hər iki cədvəldə olan bütün sətirləri qaytarır
    CROSS JOIN Bütün mümkün birləşmələri (kartesian hasil) qaytarır
    Oracle oracle innerjoin leftjoin rightjoin sql

  • JavaScript-də Prototype Chain (Prototip Zənciri)
    codexC codex

    🧬 Object.create() vasitəsilə İrsi əlaqə (Inheritance)

    JavaScript-də irsi əlaqə qurmağın başqa bir güclü və sadə yolu Object.create() metodudur. Bu metod vasitəsilə yeni bir obyekt yaradılır və bu obyektin prototipi kimi istədiyimiz digər bir obyekt təyin edilir.

    Bu üsul klassik constructor-lar və prototype zənciri qurmaqdan daha sadə və daha oxunaqlıdır.

    🧪 Nümunə:

    const animal = {
      eats: true,
      walk() {
        console.log("Animal is walking");
      }
    };
    
    const rabbit = Object.create(animal);
    rabbit.jumps = true;
    
    console.log(rabbit.eats);  // true (animal-dan miras alır)
    rabbit.walk();             // "Animal is walking"
    console.log(rabbit.jumps); // true (öz xüsusiyyəti)
    

    Bu nümunədə:

    • rabbit obyektini Object.create(animal) ilə yaratmışıq.
    • rabbit obyektində eats xüsusiyyəti yoxdur, lakin animal onun prototipidir, ona görə həmin xüsusiyyətə çatmaq mümkündür.
    • Bu, prototip zəncirinin bir hissəsidir və miras alınmış metod və xüsusiyyətlər animal obyektindən gəlir.

    ✅ Object.create() istifadəsinin üstünlükləri:

    • Daha sadə sintaksis.
    • Klassik constructor funksiyalarına ehtiyac olmadan obyekt əsaslı irsilik qurmaq imkanı.
    • Müxtəlif obyektlər arasında açıq şəkildə əlaqə yaratmaq olur.
    • Test və prototipləşdirmə üçün çox uyğundur və çevikdir.

    Beləliklə, Object.create() JavaScript-də irsi əlaqənin daha bir güclü vasitəsidir və Prototype Chain anlayışının birbaşa tətbiqini nümayiş etdirir. Bu metod xüsusilə funksional proqramlaşdırma yanaşmalarında və modul sistemlərində tez-tez istifadə olunur.

    JavaScript proto prototype object chain

  • JavaScript-də Prototype Chain (Prototip Zənciri)
    codexC codex

    JavaScript obyekt yönümlü proqramlaşdırma (OOP) yanaşmasını prototip əsaslı sistem vasitəsilə həyata keçirir. Bu, digər obyektlərin xüsusiyyətlərini miras almaq üçün klassik classlardan istifadə etmədən, obyektlər arasında birbaşa əlaqə qurulmasına imkan verir. Bu prosesə Prototype Chain, yəni Prototip Zənciri deyilir.


    🔧 Prototip nədir?

    JavaScript-də hər bir obyektin arxasında [[Prototype]] adlı gizli bir xüsusiyyət var. Bu xüsusiyyət digər obyektə (və ya null-a) istinad edir. Əgər siz bir obyektin içində müəyyən xüsusiyyət və ya metod axtarırsınızsa, JavaScript əvvəlcə həmin obyektin özündə yoxlayır, əgər tapa bilmirsə, onun prototipində axtarmağa davam edir. Bu proses Prototip Zəncirini təşkil edir.


    🔗 Prototip zəncirinin iş prinsipi

    Tutaq ki, bir obyektin içində sayHello() adlı metod yoxdur. JavaScript bu metodu həmin obyektin [[Prototype]]-ində axtarır. Əgər orada da tapa bilmirsə, növbəti prototipə keçir və bu proses null-a qədər davam edir.


    🧪 Nümunə ilə izah

    const animal = {
      eats: true,
      walk() {
        console.log("Animal is walking");
      }
    };
    
    const rabbit = {
      jumps: true
    };
    
    rabbit.__proto__ = animal; // rabbit-in prototipi animal-dır
    
    console.log(rabbit.jumps); // true (öz xüsusiyyəti)
    console.log(rabbit.eats);  // true (animal-dan miras alır)
    rabbit.walk();             // "Animal is walking"
    

    Bu nümunədə rabbit obyektində eats xüsusiyyəti yoxdur. Lakin animal onun prototipidir, ona görə rabbit.eats sorğusu true nəticəsini qaytarır.


    📐 Prototip zəncirində dərinlik

    const creature = {
      breathes: true
    };
    
    const animal = {
      eats: true,
      __proto__: creature
    };
    
    const rabbit = {
      jumps: true,
      __proto__: animal
    };
    
    console.log(rabbit.breathes); // true (creature-dan gəlir)
    

    Burada rabbit → animal → creature zənciri qurulub. rabbit.breathes çağırışı 3 səviyyəli zəncir vasitəsilə true cavabı verir.


    🔁 Prototiplər və Constructor funksiyalar

    function Person(name) {
      this.name = name;
    }
    
    Person.prototype.sayHello = function () {
      console.log("Salam, mənim adım " + this.name);
    };
    
    const user = new Person("Elvin");
    user.sayHello(); // Salam, mənim adım Elvin
    

    Burada user obyektinin sayHello metodu özündə yoxdur. JavaScript onun konstruktorunun (Person) prototype obyektinə baxır və oradan tapır.


    🧬 Object.prototype və Zəncirin sonu

    JavaScript-də bütün obyektlər nəticədə Object.prototype-dən miras alır.

    const obj = {};
    console.log(obj.toString()); // [object Object]
    

    Burada toString metodu obj-də yoxdur, lakin Object.prototype-də olduğu üçün işləyir. Ən sonda zəncir null ilə bitir:

    console.log(Object.prototype.__proto__); // null
    

    ⚠️ Diqqət: __proto__ istifadəsi

    __proto__ hələ də geniş istifadə olunur, lakin standart və tövsiyə edilən üsul Object.getPrototypeOf() və Object.setPrototypeOf() metodlarıdır.

    Object.setPrototypeOf(rabbit, animal);
    console.log(Object.getPrototypeOf(rabbit)); // animal
    

    📌 Nəticə

    • Prototip Zənciri obyektlər arasında əlaqə quraraq xüsusiyyət və metodları miras almağa imkan verir.
    • Obyektdə axtarılan xüsusiyyət tapılmadıqda, onun prototipində axtarılır və bu, null-a qədər davam edir.
    • Function.prototype, Object.prototype və digər daxili obyektlər bu zəncirin hissələridir.
    • Zəncir çox dərinə getsə belə, performans baxımından effektiv şəkildə işləyir.
    • __proto__ istifadə olunsa da, müasir və təhlükəsiz metodlar Object.getPrototypeOf() və Object.setPrototypeOf() hesab olunur.

    Təşəkkürlər ColorCode gözəl izahlı video üçün

    JavaScript proto prototype object chain

  • Oracle SQL-də CREATE, INSERT, SELECT, UPDATE və DELETE əmrləri
    codexC codex

    Oracle SQL verilənlər bazası ilə işləyənlər üçün əsas əmrlərdən bəziləri cədvəl yaratmaq, cədvələ məlumat əlavə etmək və məlumatları sorğulamaqdır. Bu əmrlər vasitəsilə siz öz bazanızı qurur, məlumatları saxlayır və onlara çıxış əldə edirsiniz.


    🧱 1. CREATE TABLE – Yeni cədvəl yaratmaq

    Oracle SQL-də yeni bir cədvəl yaratmaq üçün CREATE TABLE əmri istifadə olunur.

    Sintaksis:

    CREATE TABLE cədvəlin_adı (
        sütün_adı_1 verilənin_növü constraint,
        sütün_adı_2 verilənin_növü constraint,
        ...
    );
    

    Məsələn:

    CREATE TABLE employees (
        id NUMBER PRIMARY KEY,
        name VARCHAR2(100),
        salary NUMBER(8, 2),
        department_id NUMBER
    );
    

    Bu əmrlə employees adlı bir cədvəl yaradılır. Burada:

    • id sütunu unikal və əsas açar (PRIMARY KEY) olaraq təyin edilib.
    • name – maksimum 100 simvolluq mətn qəbul edir.
    • salary – onluq sayıdır (8 rəqəmli, 2-si onluqdan sonra).
    • department_id – işçinin aid olduğu şöbənin ID-si.

    ➕ 2. INSERT INTO – Məlumat Əlavə Etmək

    Yaradılmış cədvələ məlumat əlavə etmək üçün INSERT INTO əmri istifadə olunur.

    Sintaksis:

    INSERT INTO cədvəlin_adı (sütün_adı_1, sütün_adı_2, ...)
    VALUES (sütün 1 üçün data, sütün 2 üçün data, ...);
    

    Məsələn:

    INSERT INTO employees (id, name, salary, department_id)
    VALUES (1, 'Ali Həsənov', 2500.00, 101);
    

    Bu əmrlə employees cədvəlinə bir işçi haqqında məlumat əlavə edilir.

    Əgər bütün sütunlara ardıcıllıqla məlumat daxil edilirsə, sütun adlarını yazmadan da istifadə etmək olar:

    INSERT INTO employees
    VALUES (2, 'Aygün Məmmədova', 3200.50, 102);
    

    🔍 3. SELECT – Məlumatları Oxumaq

    Verilənlər bazasından məlumatları çıxarmaq üçün SELECT əmri istifadə olunur.

    Sintaksis:

    SELECT sütün_adı_1, sütün_adı_2 və ya *(hamısı)
    FROM cədvəlin_adı
    WHERE hər nasısa bir şərt;
    

    Məsələn:

    Bütün işçilərin adlarını və maaşlarını göstər:

    SELECT name, salary FROM employees;
    

    Maaşı 3000-dən çox olan işçiləri seç:

    SELECT * FROM employees
    WHERE salary > 3000;
    

    Bütün cədvəli görmək üçün:

    SELECT * FROM employees;
    

    ✏️ 4. UPDATE – Məlumatı Yeniləmək

    Cədvəldəki mövcud məlumatı dəyişdirmək üçün UPDATE əmri istifadə olunur.

    Sintaksis:

    UPDATE cədvəlin_adı
    SET sütün_adı_1 = sütün üçün yeni dəyər 1, sütün_adı_2= sütün üçün yeni dəyər 2, ...
    WHERE hər nasısa bir şərt;
    

    Nümunə:

    UPDATE employees
    SET salary = 2800.00
    WHERE id = 1;
    

    Bu əmrlə id-si 1 olan işçinin maaşı 2800.00 olaraq yenilənir.

    Qeyd: WHERE şərti yazılmasa, cədvəldəki bütün sətirlər yenilənər. Bu isə təhlükəlidir! UPDATE əmrini yalnız WHERE şərti ilə işlətməyi unutmuruq!


    ❌ 5. DELETE – Məlumatı silmək

    Cədvəldəki məlumatı silmək üçün DELETE əmri istifadə olunur.

    Sintaksis:

    DELETE FROM cədvəlin_adı
    WHERE hər nasısa bir şərt;
    

    Nümunə:

    DELETE FROM employees
    WHERE id = 1;
    

    Bu əmrlə id-si 1 olan işçi cədvəldən silinir.

    Diqqət: WHERE şərti yazılmazsa, bütün məlumatlar silinə bilər:

    DELETE FROM employees; -- BÜTÜN İŞÇİLƏR SİLİNƏCƏK!
    

    Oracle SQL-də əsas əmrlər:

    Əməl Təyinatı
    CREATE TABLE Yeni cədvəl yaratmaq
    INSERT INTO Yeni məlumat əlavə etmək
    SELECT Məlumatları oxumaq
    UPDATE Mövcud məlumatı dəyişdirmək
    DELETE Məlumatı silmək

    🧠 Əlavə Qeydlər

    • Datatypes (Verilən növləri):

      • VARCHAR2(n) – Mətn tipli məlumat, maksimum n uzunluqda.
      • NUMBER(p, s) – Ədədi dəyərlər: p – ümumi rəqəm sayı, s – onluqdan sonra.
      • DATE – Tarix və zaman saxlamaq üçün.
    • Constraints (Məhdudiyyətlər):

      • PRIMARY KEY – unikal və boş olmayan sütun.
      • NOT NULL – mütləq dəyər verilməlidir.
      • UNIQUE – təkrarlanmayan dəyərlər.
    Oracle sql commands create insert select

  • Proqramlaşdırma paradigmaları
    codexC codex

    Proqramlaşdırma paradigmaları — proqramların necə yazılacağını və necə qurulacağını müəyyən edən yanaşmalar və modellər toplusudur. Hər bir paradigma öz qaydaları, düşüncə tərzi və kod yazma üsulları ilə fərqlənir. Paradigmalar proqramçılara daha səliqəli, çevik və başa düşülən kod yazmaqda kömək edir.

    Bu anlayışı daha sadə şəkildə ifadə etsək, proqramlaşdırma paradigmaları – “problemi necə həll etməliyik?” sualına verilən müxtəlif cavablardır.

    03299cb3-05ef-4ace-96b7-59f096f2f8df-image.png

    🎯 Əsas proqramlaşdırma paradigmaları

    1. İmperativ paradigma

    İmperativ proqramlaşdırma, kompüterə “nə etməli” olduğunu deyil, “necə etməli” olduğunu deməkdir. Bu yanaşmada proqramçı ardıcıl əmrlərlə kompüterin nə edəcəyini təyin edir.

    Xüsusiyyətləri:

    • Dəyişənlərdən istifadə olunur
    • Addım-addım təlimat verilir
    • Nəticə ardıcıl əməliyyatlarla əldə edilir

    Məşhur dillər: C, Python, JavaScript

    Misal:

    let total = 0;
    for (let i = 1; i <= 5; i++) {
        total += i;
    }
    console.log(total); // 15
    

    2. Deklarativ paradigma

    Deklarativ proqramlaşdırma nə etmək istədiyini deyir, necə etmək lazım olduğunu isə sistem özü qərar verir. Yəni məqsədi göstəririk, amma yolu yox.

    Məşhur dillər və texnologiyalar: SQL, HTML, React (JSX)

    Misal (SQL):

    SELECT name FROM users WHERE age > 18;
    

    3. Obyekt-Yönlü (Object-Oriented Programming — OOP) paradigma

    Bu paradigma obyektlər üzərində qurulub. Obyekt — bir varlığı (nəsnəni) təmsil edir və bu varlığın xüsusiyyətləri (property) və funksiyaları (method) olur.

    Əsas prinsiplər:

    • Enkapsulyasiya (Encapsulation)
    • İrsi əlaqə (Inheritance)
    • Polimorfizm (Polymorphism)
    • Abstraksiya (Abstraction)

    Məşhur dillər: Java, C++, Python, JavaScript (ES6+)

    Misal:

    class Animal {
        speak() {
            console.log("Animal sound");
        }
    }
    
    class Dog extends Animal {
        speak() {
            console.log("Woof!");
        }
    }
    
    const dog = new Dog();
    dog.speak(); // Woof!
    

    4. Funksional paradigma

    Funksional proqramlaşdırma təmiz funksiyalara əsaslanır. Bu yanaşma dəyişənlərin dəyişdirilməməsi (immutability) və funksiyaların birinci səviyyə obyektlər kimi istifadə olunması prinsiplərinə əsaslanır.

    Xüsusiyyətləri:

    • Təmiz funksiyalar (pure functions)
    • Yan təsirsiz (no side effects)
    • Dəyişməzlik (immutability)

    Məşhur dillər: Haskell, Lisp, Elm, JavaScript (funksional üslub)

    Misal:

    const numbers = [1, 2, 3, 4];
    const doubled = numbers.map(num => num * 2);
    console.log(doubled); // [2, 4, 6, 8]
    

    🔄 Qarışıq paradigmalar

    Çoxlu proqramlaşdırma dilləri birdən çox paradigmanı dəstəkləyir. Məsələn, Python, JavaScript və C# həm obyekt-yönlü, həm də funksional yanaşmaları dəstəkləyir.


    ✅ Paradigmanın seçilməsi

    Proqramlaşdırma paradigması seçərkən aşağıdakıları nəzərə almaq faydalıdır:

    • Problem növü və miqyası
    • Komanda bacarıqları
    • Dilin imkanları
    • Performans və oxunaqlılıq

    🔚 Nəticə

    Proqramlaşdırma paradigmaları, bir problemi necə modelləşdirəcəyimizi və həll edəcəyimizi formalaşdıran çərçivələrdir. Hər bir yanaşmanın öz üstünlükləri və zəif cəhətləri var. Müasir proqramçılar bir neçə paradigmaya bələd olmalı və uyğun vəziyyətdə düzgün yanaşmanı seçməyi bacarmalıdır.

    Kompüter elmi paradigm oop imperative declarative functional

  • JavaScript-də bind, call və apply metodları
    codexC codex

    JavaScript-də funksiyalar obyektlər kimi qəbul olunur. Bu səbəbdən funksiyalara aid əlavə metodlardan istifadə etmək mümkündür. Bu metodlardan ən çox istifadə olunanları bind(), call() və apply() funksiyalarıdır. Bu metodlar vasitəsilə funksiyanın this kontekstini istədiyimiz şəkildə dəyişə bilərik.

    Bu məqalədə hər üçünü sadə və aydın şəkildə izah edəcəyik.


    1. call() Metodu

    Təyinat:

    call() funksiyası bir funksiyanı başqa bir obyektin konteksti (this) ilə çağırmağa imkan verir.

    Sintaksis:

    funksiya.call(thisArg, arg1, arg2, ...)
    
    • thisArg – funksiyanın içində this olaraq istifadə ediləcək obyekt.
    • arg1, arg2... – funksiyaya ötürüləcək arqumentlər.

    Nümunə:

    const user = {
        ad: 'Nilay',
        salamla: function(yas) {
            console.log(`Salam, mənim adım ${this.ad} və mən ${yas} yaşındayam.`);
        }
    };
    
    const digerUser = {
        ad: 'Elvin'
    };
    
    user.salamla.call(digerUser, 30);
    // Çıxış: Salam, mənim adım Elvin və mən 30 yaşındayam.
    

    İzah:

    • user.salamla funksiyası digerUser obyektinin kontekstində çağırıldı.
    • this.ad artıq digerUser obyektinə aiddir.

    2. apply() Metodu

    Təyinat:

    apply() funksiyası call() metoduna bənzəyir, yalnız arqumentlər massiv (array) şəklində verilir.

    Sintaksis:

    funksiya.apply(thisArg, [arg1, arg2, ...])
    

    Nümunə:

    function topla(a, b) {
        return a + b;
    }
    
    console.log(topla.apply(null, [5, 10])); // 15
    

    İstifadə Fərqi:

    • call() → arqumentləri ayrı-ayrı ötürürük.
    • apply() → arqumentləri massiv kimi ötürürük.

    3. bind() Metodu

    Təyinat:

    bind() funksiyası call() və apply() kimi this kontekstini dəyişmək üçün istifadə olunur, lakin funksiyanı dərhal çağırmır. Əvəzində, yeni bir funksiyanı qaytarır.

    Sintaksis:

    const yeniFunksiya = funksiya.bind(thisArg, arg1, arg2, ...)
    

    Nümunə:

    const user = {
        ad: 'Nilay'
    };
    
    function salamla(yas) {
        console.log(`Salam, mənim adım ${this.ad} və mən ${yas} yaşındayam.`);
    }
    
    const salamlaNilay = salamla.bind(user, 25);
    salamlaNilay(); // Salam, mənim adım Nilay və mən 25 yaşındayam.
    

    İstifadə Yeri:

    • Callback funksiyalar (məsələn, setTimeout, event handlers)
    • React komponentlərində this problemi

    Ümumi Müqayisə Cədvəli

    Metod this təyin edir Dərhal çağırılır Arqument ötürmə forması
    call ✔️ ✔️ Ayrı-ayrı (arg1, arg2)
    apply ✔️ ✔️ Massiv ([arg1, arg2])
    bind ✔️ ❌ (sonradan) Ayrı-ayrı (arg1, arg2)

    Real Həyat Nümunəsi: setTimeout və bind

    const user = {
        ad: 'Nilay',
        salamla: function() {
            console.log(`Salam, mənim adım ${this.ad}`);
        }
    };
    
    setTimeout(user.salamla, 1000); // undefined (çünki this itirilib)
    
    setTimeout(user.salamla.bind(user), 1000); // Salam, mənim adım Nilay
    

    Nəticə

    bind(), call() və apply() JavaScript funksiyalarında this kontekstini idarə etmək üçün əsas vasitələrdir. Onların fərqlərini və istifadələrini bilmək, daha təmiz və anlaşılan kod yazmağınıza kömək edəcək.

    • call() və apply() dərhal funksiyanı çağırır.
    • bind() isə yeni bir funksiya qaytarır və istənilən vaxt çağırmaq mümkündür.

    Bu metodlar — funksiya davranışına nəzarət etmək və təkrar istifadəni artırmaq üçün proqramçının alətlər çantasındakı vacib alətlərdəndir.

    JavaScript bind call apply this

  • JavaScript-də Closure
    codexC codex

    Closure JavaScript-də çox vacib və güclü bir anlayışdır. Bu anlayışı bilmək funksiyaların necə işlədiyini daha dərindən anlamağa kömək edir və bir çox qabaqcıl texnikaların əsasını təşkil edir.

    Sadə dillə desək, closure — bir funksiyanın özünün daxilində yaradıldığı mühitə (scope) çıxış əldə etməsi deməkdir, hətta o mühit artıq mövcud olmasa belə.


    Closure necə işləyir?

    JavaScript-də bir funksiya başqa bir funksiyanın içində yaradıldıqda, daxili funksiya xarici funksiyanın dəyişənlərinə çıxış edə bilir. Bu əlaqə closure adlanır.

    Başqa sözlə:

    • Daxili funksiya (inner function) xarici funksiyanın (outer function) dəyişənlərini “yada saxlayır” və istifadə edə bilir.

    Sadə bir nümunə

    function salamVer(name) {
        return function() {
            console.log(`Salam, ${name}!`);
        };
    }
    
    const salamNilay = salamVer('Nilay');
    salamNilay(); // Salam, Nilay!
    

    İzah:

    • salamVer funksiyası içində yeni bir funksiya qaytarır.
    • salamNilay dəyişənində salamVer funksiyası çağırılır və name dəyişəninin dəyəri Nilay olaraq yadda qalır.
    • Sonra salamNilay() çağırıldıqda, o, name dəyişəninə çıxış edir, baxmayaraq ki, salamVer funksiyası artıq icrasını bitirib.

    Bu closure nümunəsidir.


    Closure aşağıdakı hallarda faydalıdır:

    1. Məlumatların gizlədilməsi (Data encapsulation)
    2. Özəl dəyişənlər yaratmaq
    3. Funksiya fabrikləri (function factories)
    4. Currying və partial application texnikaları
    5. Asinxron kodda (məsələn, setTimeout ilə) düzgün dəyişən tutmaq

    Closure ilə dəyişənlər yaratmaq

    Closure bizə özəl (private) dəyişənlər yaratmağa imkan verir.

    Nümunə:

    function saygacYarat() {
        let say = 0;
        return {
            artir: function() {
                say++;
                console.log(say);
            },
            sifirla: function() {
                say = 0;
                console.log('Sıfırlandı');
            }
        };
    }
    
    const saygac = saygacYarat();
    saygac.artir(); // 1
    saygac.artir(); // 2
    saygac.sifirla(); // Sıfırlandı
    saygac.artir(); // 1
    

    İzah:

    • say dəyişəni saygacYarat funksiyası daxilindədir və birbaşa çöldən çıxış mümkün deyil.
    • Amma artir və sifirla funksiyaları say dəyişəninə çıxış edə bilir.

    Closure və Dövrlər (Loops)

    Closure istifadə edərkən for dövrlərində klassik səhvlər edilə bilər.

    Problemli nümunə:

    for (var i = 0; i < 3; i++) {
        setTimeout(function() {
            console.log(i);
        }, 1000);
    }
    // 3
    // 3
    // 3
    

    İzah:

    • Bütün funksiyalar eyni i dəyişəninə bağlıdır və dövr bitəndə i=3 olur.

    Doğru yanaşma (let ilə):

    for (let i = 0; i < 3; i++) {
        setTimeout(function() {
            console.log(i);
        }, 1000);
    }
    // 0
    // 1
    // 2
    

    let dəyişəni blok səviyyəli olduğuna görə hər dəfə yeni bir i yaradılır və closure düzgün işləyir.


    Closure İlə Function Factory

    Funksiya fabrikləri closure istifadə edir:

    function multiplier(x) {
        return function(y) {
            return x * y;
        };
    }
    
    const twoTimes = multiplier(2);
    const threeTimes = multiplier(3);
    
    console.log(twoTimes(5)); // 10
    console.log(threeTimes(5)); // 15
    
    • multiplier(2) çağırışında x=2 dəyəri yadda qalır və iki dəfə artıran funksiya yaranır.

    Closure xüsusiyyətləri

    Xüsusiyyət Təsviri
    Mühit Closure funksiyanın yaradıldığı mühiti saxlayır
    Uzunömürlülük Closure-lar lazımi dəyişənləri yadda saxlayır, mühit bağlansa da işləyir
    Özəl dəyişənlər Closure ilə xaricdən dəyişdirilə bilməyən dəyişənlər yaradıla bilər

    Nəticə

    Closure JavaScript proqramlaşdırmasında çox güclü bir anlayışdır. Bu konsepti başa düşmək kodunuzu daha güclü, çevik və təhlükəsiz edəcəkdir. Closure-ları başa düşən proqramçı asinxron əməliyyatları, modul dizaynını və kompleks funksiyaları daha rahat idarə edə bilər.

    Unutmayın: Closure — funksiyanın yadda saxladığı gizli bağdır.

    JavaScript closure asinxron

  • JavaScript-də hoisting
    codexC codex

    Hoisting JavaScript-də olduqca vacib və bəzən çaşdırıcı bir anlayışdır. Bu anlayışı düzgün başa düşmək səhvlərin qarşısını almağa kömək edir və kodun necə işlədiyini daha yaxşı anlamağımıza səbəb olur.

    Sadə dillə desək, hoisting o deməkdir ki, bütün dəyişənlərin və funksiyaların tanımlamaları (declarations) avtomatik olaraq kodun başlanğıcına “qaldırılır”.

    Yəni, siz dəyişən və ya funksiyanı kodda sonradan yazsanız belə, JavaScript onu icra etməzdən əvvəl başa keçirir və hazır vəziyyətə gətirir.


    Dəyişənlərdə hoisting

    JavaScript-də var, let və const ilə elan edilmiş dəyişənlər fərqli şəkildə hoisting olur.

    1. var ilə hoisting

    var ilə elan edilən dəyişənlər tam şəkildə undefined dəyəri ilə yuxarıya qaldırılır.

    Nümunə:

    console.log(a); // undefined
    var a = 5;
    console.log(a); // 5
    

    İzah:

    • JavaScript əvvəlcə var a; sətrini avtomatik olaraq kodun əvvəlinə gətirir.
    • Ona görə də birinci console.log(a); zamanı a dəyişəni mövcuddur, amma dəyəri undefined olur.

    Əslində kod belə görünür:

    var a;
    console.log(a); // undefined
    a = 5;
    console.log(a); // 5
    

    2. let və const ilə hoisting

    let və const ilə elan edilən dəyişənlər də hoisting olunur, amma onlar Temporal Dead Zone (TDZ) adlanan bir mərhələyə düşürlər.

    Bu zaman dəyişən elan olunana qədər istifadə edilərsə, ReferenceError səhvi alınır.

    Nümunə:

    console.log(b); // ReferenceError: Cannot access 'b' before initialization
    let b = 10;
    

    Nümunə const üçün də eynidir.

    Bu kod belə görünür:

    // b hoisted olur, amma dəyəri yoxdur, TDZ-dadır
    let b;
    console.log(b); // ReferenceError
    b = 10;
    

    Funksiyalarda hoisting

    Funksiya elan etmənin (function declaration) və funksiya ifadələrinin (function expression) hoisting davranışı da fərqlidir.

    1. Funksiya elanları (Function Declarations)

    Funksiya elanları tam şəkildə hoisting olunur. Yəni funksiya koddan əvvəl çağırıla bilər.

    Nümunə:

    greet(); // "Salam!"
    
    function greet() {
        console.log('Salam!');
    }
    

    İzah:

    • JavaScript bütün funksiyanı yuxarı qaldırır, ona görə greet funksiyasını əvvəl çağırmaq mümkündür.

    2. Funksiya ifadələri (Function Expressions)

    Funksiya ifadələri hoisting olunur, amma onlar dəyişən kimi davranır. Əgər var ilə elan ediliblərsə, undefined, let və const ilə elan ediliblərsə, ReferenceError verirlər.

    Nümunə (var ilə):

    console.log(add); // undefined
    var add = function() {
        console.log('Toplama');
    };
    add();
    

    Nümunə (let/const ilə):

    console.log(subtract); // ReferenceError
    const subtract = function() {
        console.log('Çıxma');
    };
    subtract();
    

    Hoisting ümumiləşdirilmiş cədvəl

    Növü Hoisting vəziyyəti
    var dəyişəni Qaldırılır, başlanğıc dəyəri undefined
    let/const dəyişəni Qaldırılır, amma TDZ-dədir
    Funksiya elanları Tam qaldırılır və istifadəyə hazırdır
    Funksiya ifadələri Qaldırılır, amma dəyişənin hoisting qaydalarına uyğundur

    Praktik töhvsiyələr

    • let və const istifadə edin: Daha təhlükəsiz və oxunaqlı kod üçün.
    • Funksiyaları əvvəlcədən elan edin: Oxumağı və anlamağı asanlaşdırır.
    • Dəyişənləri istifadə etməzdən əvvəl elan edin: Səhv ehtimalını azaldır.

    Nəticə

    Hoisting JavaScript-in əsas və vacib xüsusiyyətlərindən biridir. Dəyişənlərin və funksiyaların necə “qaldırıldığını” bilmək kod səhvlərindən yayınmağa və proqramın necə işlədiyini daha yaxşı anlamağa kömək edir.

    Unutmayın: var təhlükəli hoisting davranışına səbəb ola bilər, let və const isə daha təhlükəsizdir!

    JavaScript hoisting tdz dəyişənlər functions

  • Java-da sadə operatorlar
    codexC codex

    Java dilində operatorlar arasında ən yüksək prioritetə malik olanlar Postfiks operatorlardır (expr++, expr--).

    Operatorların prioritet sıralaması belədir (yuxarıdan aşağıya doğru):

    1. Postfiks operatorlar (expr++, expr--)
    2. Aritmetik operatorlar (+, -, *, /, %)
    3. Müqayisə operatorları (==, !=, >, <, >=, <=)
    4. Bitwise (bit əsaslı) operatorlar (&, |, ^, ~, <<, >>, >>>)

    Nəticə: Ən yüksək prioritet Postfiks operatorlar-a aiddir.

    Java operators bitwise unary ternary

  • Java-da sadə operatorlar
    codexC codex

    Java proqramlaşdırma dilində operatorlar dəyişənlər və dəyərlər üzərində müxtəlif əməliyyatlar aparmaq üçün istifadə olunur. Operatorlar proqramda əsas riyazi, məntiqi və müqayisə əməliyyatlarını icra etməyə imkan verir. Bu məqalədə Java-da istifadə olunan əsas operator növlərinə baxacağıq.


    1. Riyazi operatorlar (Arithmetic operators)

    Riyazi operatorlar ədədi dəyərlər üzərində toplama, çıxma, vurma və bölmə kimi əməliyyatlar aparır.

    Əsas riyazi operatorlar:

    • + (toplama)
    • - (çıxma)
    • * (vurma)
    • / (bölmə)
    • % (modul - qalıq tapmaq)

    Nümunə:

    int a = 10;
    int b = 3;
    System.out.println(a + b); // 13
    System.out.println(a % b); // 1
    

    2. Təkli operatorlar (Unary operators)

    Təkli operatorlar bir operand üzərində işləyir. Onlar dəyişənin dəyərini artırmaq, azaltmaq və ya mənfi etmək üçün istifadə olunur.

    Əsas təkli operatorlar:

    • + (müsbət etmək)
    • - (mənfi etmək)
    • ++ (1 artırmaq)
    • -- (1 azaltmaq)
    • ! (məntiqi inkar)

    Nümunə:

    int x = 5;
    System.out.println(++x); // 6
    System.out.println(--x); // 5
    System.out.println(-x);  // -5
    

    3. Müqayisə operatorları (Relational operators)

    Müqayisə operatorları iki dəyəri müqayisə edir və nəticə olaraq true və ya false verir.

    Əsas müqayisə operatorları:

    • == (bərabərdir)
    • != (bərabər deyil)
    • > (böyükdür)
    • < (kiçikdir)
    • >= (böyük və ya bərabərdir)
    • <= (kiçik və ya bərabərdir)

    Nümunə:

    int a = 5, b = 10;
    System.out.println(a > b);  // false
    System.out.println(a <= b); // true
    

    4. Məntiqi operatorlar (Logical operators)

    Məntiqi operatorlar bir neçə şərtin birgə qiymətləndirilməsində istifadə olunur.

    Əsas məntiqi operatorlar:

    • && (və - hər iki şərt doğru olmalıdır)
    • || (və ya - ən azı bir şərt doğru olmalıdır)
    • ! (inkar)

    Nümunə:

    boolean cond1 = true;
    boolean cond2 = false;
    System.out.println(cond1 && cond2); // false
    System.out.println(cond1 || cond2); // true
    System.out.println(!cond1);         // false
    

    5. Bitiş operatorları (Bitwise operators)

    Bitiş operatorları ikili (binary) səviyyədə bitlər üzərində əməliyyat aparır.

    Əsas bitiş operatorları:

    • & (AND)
    • | (OR)
    • ^ (XOR)
    • ~ (NOT)
    • << (sola sürüşdürmə)
    • >> (sağa sürüşdürmə)

    Nümunə:

    int a = 5;  // 0101
    int b = 3;  // 0011
    System.out.println(a & b); // 1 (0001)
    System.out.println(a | b); // 7 (0111)
    

    6. Sürüşdürmə operatorları (Shift operators)

    Sürüşdürmə operatorları bitləri müəyyən sayda sola və ya sağa hərəkət etdirir:

    • << (sola sürüşdürmə)
    • >> (sağa sürüşdürmə)

    Nümunə:

    int a = 8; // 1000
    System.out.println(a << 2); // 32 (100000)
    System.out.println(a >> 2); // 2 (10)
    

    7. Təyinat operatorları (Assignment operators)

    Təyinat operatorları dəyişənə dəyər mənimsətmək üçün istifadə olunur.

    Əsas təyinat operatorları:

    • = (sadə mənimsətmə)
    • += (toplayaraq mənimsətmə)
    • -= (çıxaraq mənimsətmə)
    • *= (vurararaq mənimsətmə)
    • /= (bölərək mənimsətmə)
    • %= (modul alaraq mənimsətmə)

    Nümunə:

    int a = 5;
    a += 3; // a = a + 3 -> a = 8
    System.out.println(a);
    

    8. Ternar operatoru (Ternary operator)

    Ternar operator sadə if-else şərtinin qısa yazılış formasıdır:

    şərt ? dəyər1 : dəyər2
    

    Əgər şərt doğru olarsa, dəyər1, əks halda dəyər2 seçilir.

    Nümunə:

    int a = 5, b = 10;
    int max = (a > b) ? a : b;
    System.out.println(max); // 10
    

    Nəticə

    Java-da operatorlar proqramların əsas hissəsini təşkil edir və müxtəlif əməliyyatları yerinə yetirmək üçün istifadə olunur. Riyazi, məntiqi, təyinat və digər operator növlərini yaxşı başa düşmək, effektiv və düzgün kod yazmaq üçün vacibdir.

    Java operators bitwise unary ternary

  • JavaScript-də Iterators və Generators
    codexC codex
    function* observerGenerator() {
        while (true) {
            console.log(`Value passed: ${yield}`);
        }
    }
    
    const obs = observerGenerator();
    obs.next('first');
    obs.next('second');
    obs.next('third');
    

    Gəlin bu generator funksiyasının necə işlədiyini addım-addım izah edək ki, niyə yalnız "second" və "third" dəyərləri ekrana çıxır, anlaşılsın.


    Addım-addım izah:

    ✅ Addım 1: Generator yaradılır

    const obs = observerGenerator();
    

    Bu sətir observerGenerator generator funksiyasını başlatmır, sadəcə obs adlı generator obyektini yaradır.


    ✅ Addım 2: obs.next('first')

    Generator ilk dəfə next('first') ilə işə salınır.

    obs.next('first');
    

    Vacib məqam: Generatorlar yield sətrinə çatana qədər kodu işlətməyə başlayır. Bizim generatorda ilk sətir bu olur:

    console.log(`Value passed: ${yield}`);
    

    Burada yield ifadəsi özündə dəyəri saxlayır, amma ilk dəfə next() çağırıldıqda, yield-ə verilən dəyər gözlənilmir, çünki generator hələ dayanmamışdı.

    • Yəni obs.next('first') çağırıldıqda:
      • Generator işə düşür,
      • yield-ə gəlib dayanır,
      • Amma yield-ə dəyər ötürülmür, ona görə də console.log(...) işləmir.

    ✅ Addım 3: obs.next('second')

    İndi isə yield artıq dayandığı yerdə gözləyir. Biz second dəyərini ötürürük:

    obs.next('second');
    
    • Bu dəyər birbaşa yield ifadəsinə ötürülür
    • console.log(...) artıq işləyir və:
      Value passed: second
      

    ✅ Addım 4: obs.next('third')

    Bu dəfə eyni proses təkrar olunur:

    obs.next('third');
    
    • third dəyəri yenə yield-ə ötürülür,
    • console.log(...) işləyir:
      Value passed: third
      

    Nəticə:

    Yalnız ikinci və üçüncü next() çağırışlarında console.log() işləyir, çünki:

    • İlk next() generatoru yield-ə qədər aparır və heç bir dəyər ötürmür (sadəcə start verir).
    • Sonrakı next(dəyər) çağırışları isə yield-ə dəyər ötürür və nəticədə console.log() işləyir.

    Qısa xülasə:

    next() çağırışı yield-ə nə ötürülür? Nəticə
    obs.next('first') Heç nə console.log() işləmir
    obs.next('second') 'second' Çıxış: Value passed: second
    obs.next('third') 'third' Çıxış: Value passed: third
    JavaScript iterators functions generators symbol

  • JavaScript-də Iterators və Generators
    codexC codex

    JavaScript-də iterators və generators, məlumatların ardıcıl emalını daha çevik və oxunaqlı şəkildə idarə etməyə imkan verir. Bu anlayışlar ES6 (ECMAScript 2015) ilə JavaScript dilinə əlavə edilib və xüsusilə custom iterable strukturların yaradılmasında, lazy evaluation və asinxron proqramlaşdırma sahələrində böyük əhəmiyyət daşıyır.


    1. Iteration Protocols (İterasiya Protokolları)

    JavaScript-də iterasiya aşağıdakı iki əsas protokol üzərindən qurulur:

    1.1 Iterable protokolu

    Bu protokol, obyektin Symbol.iterator adlı xüsusi bir metodu vasitəsilə iterasiya edilə biləcəyini göstərir. Bu metod geriyə bir iterator obyekt qaytarmalıdır.

    1.2 Iterator protokolu

    Iterator obyektində next() metodu mövcud olur. Bu metod hər çağırıldıqda obyektin növbəti dəyərini və iterasiyanın bitib-bitmədiyini bildirən { value, done } şəklində obyekt qaytarır.


    String üzərində iterator istifadə

    const text = "Rhyme";
    const it  = text[Symbol.iterator]();
    
    console.log(it.next()); // { value: 'R', done: false }
    

    Array elementlərini iterator ilə çap edilməsi

    const cities = ["Sofia", "New Delhi", "Tokyo"];
    const iterableCities = cities[Symbol.iterator]();
    
    let result = iterableCities.next();
    while (!result.done) {
        console.log(result.value);
        result = iterableCities.next();
    }
    

    Öz Iteratorumuzu yaratmaq

    class Polygon {
        constructor(...sides) {
            this.sides = sides;
        }
    
        [Symbol.iterator]() {
            let index = 0;
            return {
                next: () => {
                    if (index < this.sides.length){
                        return { value: this.sides[index++], done: false }
                    }
                    return { done: true }
                }
            };
        }
    }
    
    const poly = new Polygon(1, 2, 3, 4, 5);
    for (let side of poly) {
        console.log(side);
    }
    

    2 Generators ilə tanışlıq

    Generatorlar function* sintaksisi ilə yaradılır. Onlar yield açar sözü ilə bir-bir dəyərlər qaytarır.

    function* generator() {
        yield 1;
        yield 2;
        yield 3;
    }
    
    const gen = generator();
    console.log(gen.next().value); // 1
    console.log(gen.next().value); // 2
    

    Class daxilində generator

    class Polygon {
        constructor(...sides) {
            this.sides = sides;
        }
    
        *[Symbol.iterator]() {
           for (const side of this.sides) {
             yield side;
           }
        }
    }
    

    ID Generatoru

    function* idMaker() {
        let id = 0;
        while (true) {
            yield id++;
        }
    }
    
    const it = idMaker();
    console.log(it.next().value); // 0
    console.log(it.next().value); // 1
    

    Parametr ötürmək

    function* observerGenerator() {
        console.log('Generator created');
        while (true) {
            const value = yield;
            console.log(`Value passed: ${value}`);
        }
    }
    
    const it = observerGenerator();
    it.next(); // Başlamaq üçün ilk çağırış
    it.next(42); // Console: Value passed: 42
    

    yield* ilə generatorlar içində generator

    function* citiesGenerator() {
        yield 'Paris';
        yield* ['Rome', 'Florence', 'Berlin'];
    }
    
    const it = citiesGenerator();
    for (const city of it) {
        console.log(city);
    }
    

    Özünü yoxlmaq üçün mövzu üzrə tapşırıqlar

    Misal 1: Sadə ədədləri verən generator funksiyası yazın

    Bu məşqdə məqsəd, sadə ədədləri (prime numbers) ardıcıl olaraq verə bilən bir generator funksiyası yazmaqdır. Sadə ədədlər yalnız 1 və özündən başqa heç bir ədədə bölünməyən ədədlərdir (məsələn: 2, 3, 5, 7, 11, 13 və s.).

    Yardımçı funksiya: isPrime(num)

    const isPrime = num => {
        for (let i = 2; i < num; i++) {
            if (num % i === 0) {
                return false;
            }
        }
        return num > 1;
    };
    

    const isPrime = num => {
        for (let i = 2; i < num; i++) {
            if (num % i === 0) return false;
        }
        return num > 1;
    }
    
    function* primeNumbersGenerator() {
        let num = 2;
        while (true) {
            if (isPrime(num)) yield num;
            num++;
        }
    }
    
    const primes = primeNumbersGenerator();
    console.log(primes.next().value); // 2
    console.log(primes.next().value); // 3
    console.log(primes.next().value); // 5
    

    Misal 2: Generator ilə sual-cavab prosesi

    Bu məşqdə bir generator funksiyası yaradaraq, onun necə sual verə biləcəyini və sonradan həmin suala verilən cavabı next() metodu ilə qəbul edərək qiymətləndirəcəyini öyrənəcəyik. solveRiddle adlı generator bizə bir sual qaytarmalı (misal: What’s the Answer to the Ultimate Question of Life, the Universe, and Everything?) sonra daxil olan cavaba uyğun olaraq novbəti çağırışda true və ya false qaytarmalıdır. Misal üçün 42 yazılıbsa true.

    function* solveRiddle() {
        const question = "What's the Answer to the Ultimate Question of Life, the Universe, and Everything?";
        const answer = yield question;
        yield answer === 42;
    }
    
    const it = solveRiddle();
    console.log(it.next().value); // sualı qaytarır
    console.log(it.next(42).value); // true
    

    Misal 3: Massivin Flatten olunması (Yastılanması)

    Bu məşqdə məqsəd nested array-ləri (yəni iç-içə massivləri) istədiyimiz qədər dərinlikdə “yastılaşdırmaqdır” – yəni içərisindəki bütün elementləri tək səviyyəli array halına salmaqdır. flatten adlı bir generator function yazılmalıdır ki, o daxil olan array-in içərisindəki elementləri yield etməklə tək-tək qaytarsın. Əgər element array-dirsə və depth > 0-dırsa, həmin elementi yenidən flatten funksiyası ilə rekursiv şəkildə açmaq lazımdır (yield* istifadə etməklə).

    function* flatten(array, depth = 1) {
        for (const item of array) {
            if (Array.isArray(item) && depth > 0) {
                yield* flatten(item, depth - 1);
            } else {
                yield item;
            }
        }
    }
    
    const arr = [1, 2, [3, 4, [5, 6]]];
    const flattened = [...flatten(arr, Infinity)];
    console.log(flattened); // [1, 2, 3, 4, 5, 6]
    


    Nəticə

    JavaScript-də Iterators və Generators mövzusu, inkişaf etmiş iterasiya strukturları və performanslı həllər yaratmaq üçün güclü vasitələr təklif edir. Onlar həm custom data structures, həm də lazy evaluation, stream processing, və asinxron əməliyyatlar üçün vacibdir.

    JavaScript iterators functions generators symbol

  • CSS Flexbox
    codexC codex

    CSS Flexbox (Flexible Box Layout) veb səhifələrdə elementlərin elastik və səmərəli şəkildə yerləşdirilməsi üçün istifadə olunan güclü bir layout modelidir. Flexbox xüsusilə kompleks tərtibatlarda (naviqasiya panelləri, kart düzülüşləri, məzmun bölgüləri və s.) dizaynerlərə və proqramçılara böyük rahatlıq təmin edir. Bu məqalədə Flexbox-un əsas anlayışları, xüsusiyyətləri və istifadəsi ətraflı şəkildə izah olunacaq.

    Flexbox-un əsas anlayışları

    Flex Container və Flex Item

    Flexbox istifadəsi üçün ilk öncə bir konteyner yaradılır. Bu konteyner display: flex; və ya display: inline-flex; ilə aktivləşdirilir:

    .container {
      display: flex;
    }
    

    Bu konteyner daxilində olan bütün child elementlər (flex item-lar) artıq flexbox qaydalarına uyğun şəkildə davranacaq.

    Əsas istiqamət (Main Axis) və Çarpaz istiqamət (Cross Axis)

    Flexbox-da iki əsas ox anlayışı var:

    • Main Axis – elementlərin düzüləcəyi əsas istiqamət.
    • Cross Axis – əsas oxun əksi istiqamət.

    flex-direction xüsusiyyəti main axis-in istiqamətini təyin edir:

    .container {
      flex-direction: row;        /* Default - soldan sağa */
      flex-direction: row-reverse;
      flex-direction: column;
      flex-direction: column-reverse;
    }
    

    Elementlərin əsas oxa görə yerləşdirilməsi: justify-content

    Flex item-ları əsas ox üzrə necə yerləşdirmək istədiyinizi təyin edir:

    .container {
      justify-content: flex-start;   /* Sol tərəfə düzülür */
      justify-content: flex-end;     /* Sağ tərəfə düzülür */
      justify-content: center;       /* Ortaya düzülür */
      justify-content: space-between;/* Aralarında boşluq, kənarlar sıx */
      justify-content: space-around; /* Ətrafında bərabər boşluq */
      justify-content: space-evenly; /* Bütün boşluqlar bərabər */
    }
    

    Elementlərin çarpaz oxa görə yerləşdirilməsi: align-items

    Cross axis üzrə yerləşdirməni təyin edir:

    .container {
      align-items: stretch;     /* Default - boyu uyğunlaşdırır */
      align-items: flex-start;  /* Yuxarıya düzülür */
      align-items: flex-end;    /* Aşağıya düzülür */
      align-items: center;      /* Ortaya düzülür */
      align-items: baseline;    /* Mətnin xəttinə görə düzülür */
    }
    

    Çox sətirli flex yerləşdirmə: flex-wrap

    Elementlər bir sətrə sığmadıqda, yeni sətrə keçməsini istəyirsinizsə:

    .container {
      flex-wrap: nowrap;     /* Default - sarılmır */
      flex-wrap: wrap;       /* Sarılır */
      flex-wrap: wrap-reverse;
    }
    

    Kombinasiya üçün:

    .container {
      flex-flow: row wrap;   /* flex-direction və flex-wrap birlikdə */
    }
    

    Çoxlu sətirlərin çarpaz oxa görə yerləşdirilməsi: align-content

    Çoxlu sətirlər olduqda bütün sətirlərin cross axis üzrə yerləşməsini təyin edir:

    .container {
      align-content: flex-start;
      align-content: flex-end;
      align-content: center;
      align-content: space-between;
      align-content: space-around;
      align-content: stretch;
    }
    

    Flex item xüsusiyyətləri

    order: Elementlərin sırasını dəyişmək

    Elementlərin sırasını dəyişmək üçün:

    .item {
      order: 2; /* Default 0-dır, daha kiçik olan daha əvvəl gəlir */
    }
    

    flex-grow: Elementin böyümə qabiliyyəti

    Elementin böyümə qabiliyyəti:

    .item {
      flex-grow: 1;
    }
    

    Əgər bir neçə element flex-grow: 1; olarsa, boşluq bərabər paylaşılır.

    flex-shrink: Elementin kiçilmə qabiliyyəti

    Elementin kiçilmə qabiliyyəti:

    .item {
      flex-shrink: 1;
    }
    

    flex-basis: Başlanğıc ölçü

    Başlanğıc ölçünü təyin edir:

    .item {
      flex-basis: 100px;
    }
    

    flex: Qısa yazılış

    .item {
      flex: 1 0 100px; /* grow shrink basis */
    }
    

    align-self: Tək element üçün yerləşmə

    Xüsusi bir item üçün fərdi yerləşdirmə:

    .item {
      align-self: flex-start;
      align-self: center;
      align-self: flex-end;
      align-self: stretch;
    }
    

    Nümunə

    <div class="container">
      <div class="item">1</div>
      <div class="item">2</div>
      <div class="item">3</div>
    </div>
    
    .container {
      display: flex;
      justify-content: center;
      align-items: center;
      height: 100vh;
    }
    
    .item {
      background: #6c5ce7;
      color: white;
      padding: 20px;
      margin: 10px;
    }
    

    Flexbox, CSS-də çox güclü və geniş istifadə olunan layout texnologiyasıdır. Əgər dizaynınız dinamik və cavab verən olmalıdırsa, Flexbox sizin üçün ideal seçimdir. Tətbiqatlarda daha çevik, daha sadə və daha təmiz kod üçün Flexbox istifadə etməyi öyrənmək böyük üstünlükdür.


    Flexbox haqqında hazırlanmış bəlkə də ən yaxşı tutorial:

    CSS/SASS flexbox layout flex-direction justify-content

  • Java-da Abstraksiya
    codexC codex

    Abstraksiya (ing. Abstraction) obyekt yönümlü proqramlaşdırmanın (OOP) əsas prinsiplərindən biridir. Bu prinsip, istifadəçiyə yalnız vacib funksionallığı təqdim edərək, arxa plandakı mürəkkəb detalları gizlətməyə imkan verir. Beləliklə, istifadəçi obyektin nə etdiyini bilir, amma necə etdiyini bilməyə ehtiyac yoxdur.

    Java-da abstraksiyanın əsasları

    Java-da abstraksiya, əsasən iki vasitə ilə həyata keçirilir:

    1. Abstrakt siniflər (Abstract Classes): abstract açar sözü ilə təyin olunan classlardı. Bu classlarda həm abstrakt (gövdəsiz) metodlar, həm də konkret (gövdəli) metodlar ola bilər. Əgər bir classda ən azı bir abstrakt metod varsa, həmin class mütləq abstract olaraq təyin olunmalıdır. Abstrakt classlardan birbaşa obyekt yaratmaq mümkün deyil; onları miras alan alt classlar abstrakt metodları təyin etməlidir.

    2. İnterfeyslər (Interfaces): Yalnız abstrakt metodların (və ya Java 8-dən etibarən default və static metodların) təyin olunduğu strukturlardır. İnterfeyslər 100% abstraksiyanı təmin edir və bir class bir neçə interfeysi implement edə bilər, bu da çoxlu irsiliyi mümkün edir.

    Abstraksiya nümunəsi

    Aşağıdakı nümunədə Heyvan adlı abstrakt class və onu miras alan It classı göstərilmişdir:

    abstract class Heyvan {
       public abstract void sesCixar();
    }
    
    class It extends Heyvan {
       public void sesCixar() {
          System.out.println("It hürür");
       }
    }
    
    public class Test {
       public static void main(String args[]) {
          Heyvan h = new It();
          h.sesCixar(); // Çıxış: It hürür
       }
    }
    

    Bu nümunədə, Heyvan classı abstrakt olaraq təyin olunub və sesCixar() metodu abstraktdır. It classı bu metodu öz tələblərinə uyğun təyin edir. Test classında isə Heyvan tipində bir istinad dəyişəni ilə It obyektinə müraciət olunur və sesCixar() metodu çağırıldıqda, It classındakı versiyası icra olunur.

    Abstrakt classlar və İnterfeyslər arasındakı fərqlər

    Xüsusiyyət Abstrakt class İnterfeys
    Metodlar Həm abstrakt, həm də konkret metodlar ola bilər Yalnız abstrakt metodlar (Java 8-dən etibarən default və static metodlar da ola bilər)
    İrsilik Tək irsilik dəstəklənir Çoxlu irsilik dəstəklənir
    Obyekt yaratmaq Birbaşa obyekt yaratmaq mümkün deyil Birbaşa obyekt yaratmaq mümkün deyil

    Nəticə

    Java-da abstraksiya, proqramın mürəkkəbliyini azaltmağa və daha sadə, anlaşılan interfeyslər yaratmağa kömək edir. Bu prinsip, istifadəçiyə yalnız vacib funksionallığı təqdim edərək, arxa plandakı detalları gizlədir. Abstraksiya, proqramın saxlanmasını asanlaşdırır və genişləndirilməsini təmin edir.

    Java oop abstraction principles

  • Java-da Polimorfizm
    codexC codex

    Polimorfizm (yunanca “çox formalı”) obyekt yönümlü proqramlaşdırmanın (OOP) əsas prinsiplərindən biridir. Bu prinsip, obyektlərin bir neçə formada davranmasına imkan verir, yəni eyni metod adı ilə fərqli funksionallıqlar həyata keçirilə bilər.

    Java-da polimorfizmin əsasları

    Java-da polimorfizm, obyektin bir neçə formaya sahib olması deməkdir. Bu, əsasən iki şəkildə həyata keçirilir:

    1. Kompilyasiya zamanı polimorfizm (Compile-time Polymorphism): Metodun aşırı yüklənməsi (method overloading) ilə əldə edilir. Eyni adlı metodlar fərqli parametr siyahıları ilə təyin olunur.

    2. İcra zamanı polimorfizm (Runtime Polymorphism): Metodun yenidən təyin olunması (method overriding) ilə əldə edilir. Alt class, üst classdakı metodu öz tələblərinə uyğun yenidən təyin edir.

    Java-da polimorfizmin istifadəsi

    Polimorfizmin ən çox istifadə olunan forması, üst classın istinad dəyişəni ilə alt class obyektinə müraciət etməkdir. Bu, proqramın daha çevik və genişlənə bilən olmasını təmin edir.

    Nümunə:

    class Heyvan {
       public void sesCixar() {
          System.out.println("Heyvan səs çıxarır");
       }
    }
    
    class It extends Heyvan {
       public void sesCixar() {
          System.out.println("It hürür");
       }
    }
    
    public class Test {
       public static void main(String args[]) {
          Heyvan h = new It(); // Heyvan istinadı, It obyekti
          h.sesCixar(); // Çıxış: It hürür
       }
    }
    

    Bu nümunədə, Heyvan classın istinad dəyişəni ilə It classın obyektinə müraciət olunur. sesCixar() metodu çağırıldıqda, It classındakı versiyası icra olunur. Bu, icra zamanı polimorfizmin nümunəsidir.

    Polimorfizmin üstünlükləri

    • Kodun yenidən istifadəsi: eyni metod adı ilə fərqli funksionallıqlar həyata keçirilə bilər.
    • Çeviklik: proqramın müxtəlif hissələrində eyni interfeys ilə fərqli davranışlar əldə etmək mümkündür.
    • Genişlənəbilənlik: yeni class əlavə edildikdə mövcud kodda dəyişiklik etmədən yeni funksionallıqlar əlavə etmək mümkündür.

    Nəticə

    Java-da polimorfizm, proqramın daha çevik, genişlənə bilən və təkrar istifadə oluna bilən olmasını təmin edir. Bu prinsip, obyektlərin müxtəlif formalarda davranmasına imkan verir və proqramın strukturunu daha səmərəli edir.

    Java oop polymorphism principles

  • Java-da İrsi̇li̇k (Inheritance)
    codexC codex

    İrsilik (ing. Inheritance) obyekt yönümlü proqramlaşdırmanın (OOP) əsas prinsiplərindən biridir. Bu prinsip, bir classın başqa bir classın xüsusiyyətlərini (metodlar və dəyişənlər) əldə etməsinə imkan verir. İrsilik, kodun təkrar istifadəsini təmin edir və proqramın strukturunu daha sadə və anlaşılan edir.

    Java-da irsiliyin əhəmiyyəti

    • Kodun yenidən istifadəsi: Bir dəfə yazılmış kodu digər classlarda təkrar istifadə etməyə imkan verir.
    • Genişlənəbilənlik: Mövcud classların funksionallığını genişləndirməyə şərait yaradır.
    • Metodun yenidən təyin edilməsi (Overriding): Alt classlarda üst classların metodlarını yenidən təyin etməyə imkan verir.
    • Abstraksiyanın əldə edilməsi: Abstraksiya prinsipi irsilik vasitəsilə həyata keçirilə bilər.

    Java-da irsiliyin tətbiqi

    Java-da irsiliyi tətbiq etmək üçün extends açar sözündən istifadə olunur. Bu, bir classın digər classın xüsusiyyətlərini miras almasını təmin edir.

    İrsiliyin sintaksisi

    class SuperClass {
       // Üst classın xüsusiyyətləri
    }
    
    class SubClass extends SuperClass {
       // Alt classın əlavə xüsusiyyətləri
    }
    

    Java-da irsilik nümunəsi

    Aşağıdakı nümunədə Calculation adlı üst class və My_Calculation adlı alt class yaradılmışdır. My_Calculation classı Calculation classdan addition() və subtraction() metodlarını miras alır və əlavə olaraq multiplication() metodunu təqdim edir.

    class Calculation {
       int z;
    
       public void addition(int x, int y) {
          z = x + y;
          System.out.println("Verilən ədədlərin cəmi: " + z);
       }
    
       public void subtraction(int x, int y) {
          z = x - y;
          System.out.println("Verilən ədədlərin fərqi: " + z);
       }
    }
    
    public class My_Calculation extends Calculation {
       public void multiplication(int x, int y) {
          z = x * y;
          System.out.println("Verilən ədədlərin hasilə: " + z);
       }
    
       public static void main(String args[]) {
          int a = 20, b = 10;
          My_Calculation demo = new My_Calculation();
          demo.addition(a, b);
          demo.subtraction(a, b);
          demo.multiplication(a, b);
       }
    }
    

    Java-da irsiliyin növləri

    Java-da əsasən üç növ irsilik mövcuddur:

    1. Tək irsilik (Single Inheritance): Bir alt class bir üst classdan miras alır.
    2. Çoxsəviyyəli irsilik (Multilevel Inheritance): Bir class başqa bir classdan miras alır və həmin classda başqa bir classdan miras alır.
    3. Hierarxik irsilik (Hierarchical Inheritance): Bir neçə alt class eyni üst classdan miras alır.

    Qeyd: Java çoxlu irsiliyi (Multiple Inheritance) classlar səviyyəsində dəstəkləmir. Bu, “diamond problem” adlanan qeyri-müəyyənlikdən qaçmaq üçün nəzərdə tutulmuşdur. Lakin, Java interfeyslər vasitəsilə çoxlu irsiliyi təmin edir.

    Nəticə

    Java-da irsilik, proqramın strukturunu daha səmərəli və təkrar istifadə edilə bilən hala gətirir. Bu prinsip, kodun saxlanmasını asanlaşdırır və proqramın genişləndirilməsini təmin edir. İrsiliyin düzgün tətbiqi, obyekt yönümlü proqramlaşdırmanın gücündən tam istifadə etməyə imkan verir.

    Java oop inheritance principles

  • Java-da Enkapsulyasiya
    codexC codex

    Enkapsulyasiya obyekt yönümlü proqramlaşdırmanın (OOP) əsas prinsiplərindən biridir. Bu prinsip, məlumatların (dəyərlərin) və həmin məlumatlar üzərində işləyən metodların bir yerdə saxlanılmasını təmin edir. Java-da enkapsulyasiya, class daxilindəki dəyişənlərin digər classlardan gizlədilməsi və yalnız həmin classın metodları vasitəsilə əldə olunması ilə həyata keçirilir. Bu səbəbdən, enkapsulyasiya tez-tez “məlumatların gizlədilməsi” (data hiding) adlandırılır.

    Java-da enkapsulyasiya necə tətbiq olunur?

    Java-da enkapsulyasiyanı həyata keçirmək üçün aşağıdakı addımlar izlənilir:

    1. Dəyişənləri private elan etmək: Bu, həmin dəyişənlərin yalnız aid olduqları class daxilində əlçatan olmasını təmin edir.
    2. public getter və setter metodları təmin etmək: Bu metodlar vasitəsilə dəyişənlərin dəyərləri oxunur və dəyişdirilir.

    Bu yanaşma, classın daxilindəki məlumatların birbaşa müdaxilədən qorunmasını və yalnız müəyyən edilmiş metodlar vasitəsilə idarə olunmasını təmin edir.

    Java-da enkapsulyasiya nümunəsi

    Aşağıdakı nümunə, Java-da enkapsulyasiyanın necə tətbiq olunduğunu göstərir:

    public class EncapTest {
       private String name;
       private String idNum;
       private int age;
    
       public int getAge() {
          return age;
       }
    
       public String getName() {
          return name;
       }
    
       public String getIdNum() {
          return idNum;
       }
    
       public void setAge(int newAge) {
          age = newAge;
       }
    
       public void setName(String newName) {
          name = newName;
       }
    
       public void setIdNum(String newId) {
          idNum = newId;
       }
    }
    

    Bu classdaname, idNum və age dəyişənləri private olaraq elan edilmişdir, yəni onlar yalnız EncapTest classı daxilində əlçatandır. Bu dəyişənlərin dəyərlərini oxumaq və dəyişdirmək üçün isə public getter və setter metodları təmin olunmuşdur.

    Enkapsulyasiyanın üstünlükləri

    • Məlumatların qorunması: dəyişənlər birbaşa müdaxilədən qorunur, bu da proqramın təhlükəsizliyini artırır.
    • Modul dizayn: classlar arasında əlaqələr minimuma endirilir, bu da proqramın saxlanmasını və genişləndirilməsini asanlaşdırır.
    • Kodun oxunaqlılığı və idarə olunması: dəyişənlərə yalnız müəyyən metodlar vasitəsilə daxil olmaq, kodun daha oxunaqlı və idarəolunan olmasını təmin edir.

    Nəticə

    Java-da enkapsulyasiya, proqramın təhlükəsizliyini və strukturlaşdırılmasını təmin edən vacib bir OOP prinsipidir. Dəyişənlərin private elan edilməsi və public getter və setter metodları vasitəsilə idarə olunması, məlumatların qorunmasını və proqramın daha etibarlı olmasını təmin edir. Bu yanaşma, böyük və kompleks proqramların inkişafında xüsusilə faydalıdır.

    Java oop encapsulation principles
  • 1 / 1
  • Daxil ol

  • Sizin hesabınız yoxdur? Qeydiyyatdan keç

  • Axtarış etmək üçün daxil olun və ya qeydiyyatdan keçin.
  • İlk yazı
    Son yazı
0
  • Kateqoriyalar
  • Ən yeni
  • Teqlər
  • Populyar