Page cover image

Scope of Variables

พศุตม์ อุ่นไธสง 650710089

Scope of Variables คืออะไร ?

Scope of Variables หรือ ขอบเขตของตัวแปร เราสามารถนิยามได้ว่ามันหมายถึง ขอบเขตพื้นที่ที่เราสามารถเข้าถึงตัวแปรนั้นๆ เพื่อใช้งานค่าที่ตัวมันเก็บเอาไว้ได้ ซึ่งตัวแปรพวกนั้นอาจมีรูปแบบของค่าอยู่ในรูปแบบ reference types หรือแบบ value types ก็ได้


Scope of Variables ใน C#

(Scope of Variables in C#)

ในภาษา C# มีการแบ่งขอบเขตของตัวแปรออกเป็น 3 รูปแบบ:

  • Class Level Scope

  • Method Level Scope

  • Block Level Scope

Class Level Scope

Class Level Scope หรือ ขอบเขตระดับคลาส หมายถึง การที่ตัวแปรตัวนั้น สามารถเข้าถึงจากส่วนไหนก็ได้ ไม่ว่าจะเป็นการเข้าถึงผ่านตัวแปร หรือเมธอดอื่นๆ ภายในคลาสที่ตัวแปรนั้นมีการประกาศค่าเอาไว้อยู่ และยังสามารถเข้าถึงตัวแปรในระดับนี้ได้โดยผ่านการใช้งานสิ่งที่เรียกว่า Access Modifier

using System;

class Student{ // Class level scope starts from here
    
    // Declaring a variable
    // These are on class level scope
    string stdID = "650710089";
    string name = "Pasut";
    int year = 3;
    
    // Declaring a method
    public void sayHelloToStudent(){
    
        // Can access stdID that is a class level variable.
        Console.WriteLine("Hello! " + stdID + " " + name + " year: " + year);
        
    }
    
} // Class level scope ends here 

จากตัวอย่าง ตัวแปร stdID มีการประกาศค่าอยู่ภายในคลาส Student หมายความว่าตัวแปร stdID สามารถเข้าถึงได้จากทุกพื้นที่ของคลาส Student

Method Level Scope

Method Level Scope หรือ ขอบเขตระดับเมธอด หมายถึง การที่ตัวแปรตัวนั้น สามารถเข้าถึงจากส่วนไหนก็ได้ภายในเมธอดที่ตัวแปรนั้นมีการประกาศค่าเอาไว้อยู่

using System;

class Student{ 
    
    // Declaring a variable
    // These are on method level scope
    string stdID = "650710089";
    string name = "Pasut"
    int year = 3;
    
    // Declaring a method
    public void sayHelloToStudent(){ // Method level scope starts from here
    
        // Declaring a variable
        // "text" is a method level variable
        string text = "Hello! " + stdID + " " + name + " year: " + year;
        Console.WriteLine(text);
        
    } // Method level scope ends here
    
    public void sayHelloToStudentAgain(){
    
        // This will give a complie-time error
        Console.WriteLine(text);
        
    }
    
}

จากตัวอย่าง ตัวแปร text มีการประกาศค่าอยู่ภายในเมธอด sayHelloToStudent() หมายความว่าตัวแปร text สามารถเข้าถึงได้แค่ภายในเมธอด sayHelloToStudent() เท่านั้น

จะเห็นได้ว่าเมื่อเราเมื่อทำเรียกใช้ตัวแปร text จากเมธอด sayHelloToStudentAgian() จะเกิดเหตุการณ์ complie-time error ได้ เพราะว่าเมธอดดังกล่าว ไม่สามารถเข้าถึงตัวแปร text ที่อยู่ในอีกเมธอดได้ เนื่องจากขอบเขตของตัวแปร text อยู่แค่ภายในเมธอด sayHelloToStudent()

Block Level Scope

Block Level Scope หรือ ขอบเขตระดับบล็อค หมายถึง การที่ตัวแปรตัวนั้น สามารถเข้าถึงจากส่วนไหนก็ได้ภายในบล็อคของโปรแกรมที่ตัวแปรนั้นมีการประกาศค่าเอาไว้อยู่ เช่น ตัวแปรที่ถูกประกาศค่าภายใน for, while-loop และอื่นๆ

using System;

class Student{

    // Declaring a variable
    // These are on block level scope
    string stdID = "650710089";
    string name = "Pasut";
    int year = 3;
    
    // Declaring a method
    public void sayHelloToStudentManyTimes(){
    
        string text = "Hello! " + stdID + " " + name + " year: " + year;
    
        for(int i = 1; i <= 3; i++){ // Block level scope starts from here
    
            Console.WriteLine(text);
            
        } // Block level scope ends here
        
        // This will give a complie-time error
        Console.WriteLine("Total times saying hello: " + i);

    }
    
}

จากตัวอย่าง ตัวแปร i ที่มีการประกาศค่าอยู่ภายใน statement ของ for-loop ภายในคลาส sayHelloToStudentManyTimes() หมายความว่าตัวแปร i สามารถเข้าถึงได้แค่ภายในเมธอด for ที่ตัวแปรมีการประกาศค่าอยู่เท่านั้น

จะเห็นได้ว่าเมื่อเราเมื่อทำเรียกใช้ตัวแปร i จะเกิดเหตุการณ์ complie-time error ได้ เนื่องจากขอบเขตของตัวแปร i นั้น สามารถเข้าถึงได้แค่ภายใน for ที่มีการประกาศตัวแปร i เอาไว้


Scope of Variables ใน C# ต่างจากภาษาอื่นอย่างไร ?

ในแต่ละภาษาก็จะมีการออกแบบขอบเขตของตัวแปรที่คล้าย หรือแตกต่างกันไป ตามลักษณะการใช้งานในแต่ละภาษาโดยจะยกตัวอย่างมาเปรียบเทียบ 3 ภาษา ได้แก่ Java, C และ Python

Java

(Scope of Variables in Java)

ในภาษา Java ก็มีการแบ่งขอบเขตของตัวแปรเป็นรูปแบบเดียวกับภาษา C# โดยแบ่งเป็น 3 รูปแบบ:

  • Class Level Scope (Member Variables)

  • Method Level Scope (Local Variables)

  • Block Level Scope (Loop Variables)

class Student{

    // Declaring a variable
    // These are class level variable
    String stdID = "650710089";
    String name = "Pasut";
    int year = 3;
    
    // Declaring a method
    public void sayHelloToStudent(){
    
        // Can access stdID that is a class level variable.
        System.out.println("Hello! " + stdID + " " + name + " year: " + year);
        
    }
    
}

C

(Scope of Variables in C)

ในภาษา C จะมีรูปแบบการแบ่งขอบเขตของตัวแปรที่ต่างออกไป เนื่องจากภาษา C ไม่ได้ออกแบบมารองรับการเขียนโปรแกรมเชิงวัตถุ (Object-Oriented Programming: OOP) จึงได้มีการออกแบบการแบ่งขอบเขตในอีกรูปแบบหนึ่ง โดยแบ่งออกเป็น 2 รูปแบบ:

  • Global Level Scope

  • Local Level Scope

Global Level Scope

Global Level Scope ในภาษา C จะเป็นตัวแปรที่มีการเอาไว้ที่บนสุดของโปรแกรมเลย เพื่อให้การทำงานทั้งหมดที่อยู่ด้านล่างของตัวแปรนี้ สามารถเข้าถึงตัวแปรนี้ได้จากทั้งโปรแกรมเลย

#include <stdio.h>

// Declaring a variable
// "year" is on global scope
int year = 5;

void printYear1(){

    // Can access "year" that is on global scope
    printf("From year1: %d\n", year);
}

void printYear2(int num){
    printf("From year2: %d\n", num);
}

void main(){
    printYear1();
    
    // Can access "year" without having to redeclair variable
    year = 3;
    printYear2(year);
}
Result
From year1: 5
From year2: 3

จากตัวอย่าง จะเห็นว่าตัวแปร year สามารถเข้าถึงได้จากทุกที่ ตั้งแต่ด้านล่างที่ตัวแปรนั้นถูกประกาศเอาไว้เลย และยังสามารถเปลี่ยนแปลงค่าของตัวแปรนั้นได้โดยตรงอีกด้วย

จะเห็นได้ถึงความแตกต่างจากการทำงานภาษา C# ที่จะมีขอบเขตที่ค่อนข้างชัดเจน เช่น Class Level Scope ก็จะสามารถเข้าถึงได้เฉพาะการทำงานภายในคลาสนั้น แต่ Global Level Scope ขอแค่เพียงประกาศตัวแปรเอาไว้บนสุดของโปรแกรม ก็สามารถใช้ตัวแปรนั้นจากตรงไหนของโปรแกรมเลยก็ได้ ขอเพียงแค่อยู่ด้านล่างตัวแปรนั้น

Local Level Scope

Local Level Scope ในภาษา C จะเป็นการประกาศตัวแปรนั้นเอาไว้ในฟังก์ชัน หรือในบล็อคของโปรแกรม โดยในภาษา C มีการแบ่ง Local Scope ออกเป็น 2 รูปแบบ:

  • Function Scope Local

  • Block Scope Local

#include <stdio.h>

void printYear1(){

    // Declaring variable
    // "year" is on function local scope
    int year = 5;
    printf("From year1: %d\n", year);
}

void main(){
    printYear1();
}
Result
From year1: 5

จากตัวอย่าง ตัวแปร year ที่อยูในฟังกชัน printYear1() มีการประกาศตัวแปรขึ้นมาใหม่ ทำให้ตัวแปร year สามารถเข้าถึงได้ในเฉพาะภายในฟังก์ชันนี้เท่านั้น ไม่สามารถเข้าถึงจากภายนอกได้

ถ้าลองสังเกตดูตัวแปรแบบ Function Scope Local ของภาษา C จะมีลักษณะที่คล้ายคลึงกับ Method Level Scope ในภาษา C# และ Java เลย คือมีการจำกัดขอบเขตของตัวแปรให้สามารถเข้าถึงได้จากภายในเมธอด หรือฟังก์ชันที่ตัวแปรมีการประกาศอยู่เท่านั้น ส่วน Block Scope Local จะค่อนข้างต่างจากภาษา C# อยู่ เพราะในภาษา C ขอแค่อยู่ต่างบล็อคของโปรแกรม หรือใน { } ที่ต่างกัน ก็ถือเป็นอีกตัวแปรเลย เนื่องด้วยอิสระในการเขียนของภาษา C ค่อนข้างสูง ซึ่งหากทำเช่นนี้ในภาษา C# และ Java จะเกิดเป็น error ได้ แต่ในส่วนที่เป็น for-loop ยังมีการมองขอบเขตเป็นรูปแบบเดียวกันอยู่

Python

(Scope of Variables in Python)

ในภาษา Python มีการแบ่งขอบเขตของตัวแปรออกเป็น 3 รูปแบบ:

  • Global Level Scope

  • Nonlocal Level Scope

  • Local Level Scope

Global Level Scope

Global Level Scope ในภาษา Python เป็นการประกาศตัวแปรที่มีประกาศรไว้นอกฟังก์ชันใดๆ โดยตัวแปรนี้สามารถเข้าถึงได้ไม่ว่าจะเป็นภายนอก หรือภายในฟังก์ชัน

# declare global variable
text = 'Hello! 650710089'

def sayHelloToStudent():
    # declare local variable
    print('Local:', text)

sayHelloToStudent()
print('Global:', text)
Result
Local: Hello! 650710089
Global: Hello! 650710089

จากตัวอย่าง จะเห็นได้ว่าผลลัพธ์ที่แสดงจากภายในฟังก์ชัน sayHelloToStudent() มีค่าเหมือนกับที่แสดงค่าจากภายนอกฟังก์ชัน เพราะตัวแปร text เป็น global variable ทำให้สามารถเข้าได้ทั้งหมดจากทั้งใน และนอกฟังก์ชัน

จะเห็นได้ว่าลักษณะการทำงานคล้ายคลึงกับในภาษา C ซึ่งแตกต่างจากภาษา C# ที่ต้องมีขอบเขตที่ชัดเจน ว่าเป็นตัวแปรระดับคลาส เมธอด หรือบล็อค

Nonlocal Level Scope

ในภาษา Python มีขอบเขตชนิดหนึ่ง ที่แตกต่างจากภาษาอื่นนั่นคือ Nonlocal Level Scope ซึ่งมี keyword ที่สำคัญคือ nonlocal

nonlocal จะถูกใช้เมื่อเราต้องการจะเข้าถึงตัวแปรที่อยู่นอกฟังก์ชัน เพราะในภาษา Python ต่อให้ตัวแปรมีชื่อเดียวกัน แต่ตัวแปรอยู่คนละขอบเขตกัน ก็จะถือว่าเป็นคนละตัวกัน

จึงได้มีการใช้ nonlocal เพื่อบอกว่าตัวแปรด้านในที่เป็นตัวแปรแบบ local เป็นตัวเดียวกับที่อยู่ด้านนอก

ไม่มีการใช้ nonlocal

# outside function 
def outer():
    text = 'local'

    # nested function  
    def inner():
        
        # no declare nonlocal variable
        text = 'nonlocal'
        print('Inner:', text)

    inner()
    print('Outer:', text)

outer()
Result
Inner: nonlocal
Outer: local

จะเห็นได้ว่าผลลัพธ์ที่แสดงจากภายในฟังก์ชัน inner() มีค่าต่างจากที่แสดงจากฟังก์ชัน outer()


ใช้ nonlocal

# outside function 
def outer():
    text = 'local'

    # nested function  
    def inner():

        # declare nonlocal variable
        nonlocal text

        text = 'nonlocal'
        print('Inner:', message)

    inner()
    print('Outer:', message)

outer()
Result
Inner: nonlocal
Outer: nonlocal

แต่พอมีการใช้ nonlocal ค่าที่ออกมาจะเหมือนกัน เพราะเราทำให้โปรแกรมมองว่าตัวแปร text ที่อยู่ในฟังก์ชัน inner() เป็นตัวเดียวกับที่อยู่ด้านนอก

เป็นขอบเขตที่มีลักษณะพิเศษต่างจากภาษาอื่นๆ ซึ่งอาจทำให้ดูสับสนในการใช้งานได้ ถ้าหากเราต้องการที่จะเปลี่ยนแปลงค่าตัวแปรที่อยู่ด้านนอก

Local Level Scope

Local Level Scope ในภาษา Python เป็นการประกาศตัวแปรที่มีประกาศไว้ในฟังก์ชันใดๆ โดยที่ตัวแปรตัวนั้นจะสามารถเข้าถึงได้แค่จากด้านในฟังก์ชันที่ตัวแปรมีการประกาศค่าไว้เท่านั้น

def sayHelloToStudent():

    # local variable
    text = 'Hello! 650710089'
    
    print('Local:', text)

sayHelloToStudent()

# try to access message variable 
# outside greet() function
print(text)
Result
NameError: name 'text' is not defined

จากตัวอย่าง จะเห็นว่ามี error เกิดขึ้น เพราะว่าตัวแปร text เป็น local variable ที่อยู่ในฟังก์ชัน sayHelloToStudent() ทำให้เมื่อมีการแสดงค่าของตัวแปร text ที่ด้านนอกฟังก์ชัน เกิดเป็น error ขึ้น

Local Scope ค่อนข้างมีความคล้ายคลึงกับในภาษาอื่นๆ คือเป็นตัวแปรที่อยู่ในขอบเขตของฟังก์ชัน ไม่สามารถเข้าถึงตัวแปรนี้จากภายนอกฟังก์ชันได้


Video & Presentation

(Scope of Variables in C#)

Reference

  • เว็บไซต์นี้ใช้ดูวิดีโอ เพื่อเพิ่มเข้าใจเกี่ยวกับหลักการทำงานของเรื่อง Scope ของตัวแปรใน ภาษา C#

  • เว็บไซต์นี้ใช้ดูเนื้อหา และรายละเอียดเกี่ยวกับ Scope of Variables ของภาษา C#

  • เว็บไซต์นี้ใช้ดูเนื้อหา และรายละเอียดเกี่ยวกับ Scope of Variables ของภาษา C

  • เว็บไซต์นี้ใช้ดูเนื้อหา และรายละเอียดเกี่ยวกับ Scope of Variables ของภาษา Java

  • เว็บไซต์นี้ใช้ดูเนื้อหา และรายละเอียดเกี่ยวกับ Scope of Variables ของภาษา Python

  • เว็บไซต์นี้ใช้ดูเนื้อหา และรายละเอียดเพิ่มเติมเกี่ยวกับเรื่อง Nonlocal Scope ของภาษา Python

Last updated