All articles
รวมเอกสาร CSSep 06, 20230 min read

OOP เนื้อหาไฟนอล 2023/1

Object-Oriented Programming เนื้อหาไฟนอล 2023/1

A

Athicha Leksansern

Full-stack Engineer

แนวข้อสอบ

มี 3 ตอน เก็บ 40% 87 คะแนน

  • ตอนที่ 1 (40 คะแนน)
    1. หาผลลัพท์โปรแกรม
      • Inheritance / Polymophism / Static Binding / Dynamic Binding
    2. ตอบคำถามเรื่อง
      • Inheritance + implements คราส Interface
    3. เขียนโปรแกรม Interface
    4. ตอบคำถามถูกผิดเกี่ยวกับ ... + interface
    5. เขียนโปรแกรม Dynamic Binding
    6. หาผลลัทธ์ Graphics
  • ตอนที่ 2 เขียนโปรแกรม GUI + Event 2 ข้อ \approx 20 คะแนน
  • ตอนที่ 3 เขียนโปรแกรม Algorithm 2 ข้อ \approx 15 คะแนน

Week 10 Inheritance

OOP Concept

  1. Abstraction: มองทุกอย่างเป็น Class และ object
  2. Encapsulation: การป้องกันข้อมูล
    • Public
    • Private
    • Protected
  3. Inheritance: การสืบทอดคุณสมบัติ
  4. Polymorphism: การมีหลายรูปแบบ
    • Overriding
    • Overloading
    • Dynamic binding
    • Static binding

Type of Classes

  • Super Class หรือ General Class
    • เช่น Student: id, firstName, lastName
  • Sub Class: Specific class
    • Class ลูกจะมี Attribute และ Methods เหมือนแม่
    • เช่น Bachelor student: ป. ตรี
// Super Class
class A {
  int x;
  void f() {}
}

// Sub Class (B)
// From Super Class A
class B extends A {
  int y;
  void g() {}
}

Inheritance example

โดยปกติแล้ว Java จะทำการ Inheritance Class Object อยู่แล้ว (โดยอัตโนมัติ) ซึ่งประกอบไปด้วย Methods ต่างๆ เช่น getClass(), hashCode(), equals(), clone(), toString(), notify(), notifyAll(), wait()

@Override

  • การเปลี่ยน Behavior ของ Methods ใน Sub Class ที่ Inheritance มาจาก Super Class ด้วยการ @Override
class A {
  private int z;

  // เป็นการ Override methods ของ Super Class ชื่อ Object เป็น Built-in ของ Java
  @Override
  public String toString() {
    z = 5;
    return "result: " + z;
  }
}

// สร้าง Object
A a = new A();
System.out.println(a.toString());
System.out.println(a);

Protected vs Private

  • ถ้า Parent class มีการเข้าถึงแบบ private, class ลูกจะไม่สามารถใช้ได้
  • แต่ถ้าเป็น protected หรือ public, class ลูกจะสามารถใช้ได้

super

  • super() คือ Contructor ที่มาจาก Super class
  • Constructor Chaining: คือการเรียก Constructor จากหลายๆ Class
    • เวลา extends มันจะแอบใส่ super() ของ Class แม่เข้ามาให้ก่อน (โดยอัตโนมัติ)

Constructor Chaining

public class Faculty extends Employee {
  public static void main(String[] args) {
    new Faculty();
  }

  public Faculty() {
    System.out.println("(4) Faculty's no-arg constructor is invoked");
  }
}

class Employee extends Person {
  public Employee() {
    this("(2) Invoke Employee's overloaded constructor");
    System.out.println("(3) Employee's no-arg constructor is invoked");
  }

  public Employee(String s) {
    System.out.println(s);
  }
}

class Person {
  public Person() {
    System.out.println("(1) Person's no-arg constructor is invoked");
  }
}
  • จะไม่สามารถใช้ Point(x, y) ใน Point3D ได้
class Point {
  private int x;
  private int y;

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

class Point3D extends Point {
  private int z;

  Point3D(int x, int y, int z) {
    super(x, y);
    this.z = z;
  }
}
  • Code นี้จะ error เพราะ Java จะใส่ super() มาใหแต่ Class Fruit ดันไม่มี Default Constructur ต้องแก้เป็นเพิ่ม public Fruit() {}
public class Apple extends Fruit {
  // ...

  // Java จะสร้างสิ่งนี้ให้
  // public Apple() {
  //   super();
  // }
}

class Fruit {
  // ไม่มี Default Constructor เพราะถ้าสร้าง Constructor แบบอื่นไปแล้ว
  public Fruit(String name) {
    System.out.println("Fruit's constructor is invoked");
  }
}
  • นอกจาก super จะเป็น Constructor super ยังสามารถเรียก Attribute และ Methods ได้เหมือนกัน
public void printCircle() {
  System.out.println("The circle is created " + 
  // super.getDateCreated() คือ Methods จาก Class แม่
  super.getDateCreated() + " and the radius is " + radius);
}

Overloading

void f() {}
void f(int x) {}
void f(double x) {}

Overriding

จะไม่สามารถทำให้ Visibility น้อยลงได้

แม่ protected -> ลูก default, protected private -> private public -> public

From,To\dArr \text{From}, \text{To} \rArrPublicProtectedDefaultPrivate
Public
Protected
Default
Private

Shadowing

  • เมื่อมีตัวแปรชื่อเหมือนกัน ตัวแปรที่ใกล้ที่สุดจะโดนเรียกก่อน แล้วตัวแปรที่สูงกว่านั้นจะถูก shadowed
public class ShadowApp {
  static int x;
  public static void main(String[] args) {
    x = 5; // Class
    System.out.println("x = " + x); // Class
    int x; // Local
    x = 10; // Local
    System.out.println("x = " + x); // Local
    System.out.println("ShadowApp.x = " + ShadowApp.x); // Class
  }
}
  • ถ้า Inherite มาจะเรียกว่าเป็นตัวแปร Inherited scope

Scope

Week 11 Polymorphism

Polymorphism

  • ตัวแปร 1 ตัวมีการประกาศและมีตัวแปรประเภทได้มากกว่า 1 ชนิด

    // Super type
    class Animal { }
    // Sub type
    class Cat extends Animal { }
    class Dog extends Animal { }
    
    // ปกติ: Super -> Super
    Animal a = new Animal();
    Cat c = new Cat();
    Dog d = new Dog();
    
    // Polymorphism: Super -> Sub
    Animal a = new Cat();
    a = new Dog();
    
    // ❌: Sub -> Super
    // สัตว์ ทุกตัวไม่ใช่ แมว!
    Cat c = new Animal();
    

Static Binding & Dynamic Binding

  • Static binding: คือการเช็คว่า Class นั้นมี methods นี้ไหม (Compile)

  • Dynamic binding: คือการเช็ค / เลือกว่า methods นั้นจาก Object นั้นจะไปรันของ Class ไหน (Runtime)

  • Generic Programming: คือการประกาศรับ Class ให้มันกว้างๆ ไว้ก่อน

    // Polymorphism
    m(new GraduateStudent());
    m(new Student());
    m(new Person());
    m(new Object());
    
    // Generic Programming
    public static void m(Object x) {
      // 1. Static binding
      // 2. Dynamic binding
      System.out.println(x.toString());
    }
    

instanceof

  • เมื่อทำการเขียน Function แบบ Generic Programming แล้วต้องการใช้ methods ใน Sub Class จะไม่ผ่านตอน Static binding เนื่องจาก Super Class ไม่มี

  • ถ้าหาก Casting มาจะไม่ผิด Compile (Static binding) แต่เมื่อเรียกใช้ methods ที่อยู่ใน Sub Class, java จะทำการ Dynamic binding เพื่อไปเช็คว่า Class ของ Object นั้นๆ มี methods ไหม ซึ่งอาจจะไม่มี

  • จึงสามารถเช็คประเภทของ Object ได้ตรงๆ โดยการใช้ instaceof

    public static void m(Object x) {
      if(x instanceof Student) {
        ((Student) x).study();
      } else {
        System.out.println("Not a student!");
      }
    }
    

Object methods

  • toString(): เลข Reference ของ Object
  • equals(): เช็คว่าตำแหน่งเดียวกันไหม

Week 12 Abstract

Abstract Class & Abstract Methods

  • Abstract ช่วยให้เขียน Code ให้ Safe มากขึ้นจากการให้บังคับ Implements methods ให้ครบทุกอัน

    • เช่น หากมี Class แม่ และ ลูก Inherite อาจจะลืม implement methods จากแม่ และทำให้ผลลัพท์ผิดพลาด
    // จะไม่สามารถนำ Abstract class มาสร้าง Object ได้
    // แต่ถ้าทำ Polymoriphm จาก Geometrics ได้
    Geometrics obj = new Circle();
    
    // base class
    abstract class Geometrics {
      int w, h;
      int r;
      double area, perimeter;
      // methods ไม่สมบูรณ์
      abstract double calArea();
      abstract double calPerimeter();
    }
    
    // subclass
    class Circle extends Geometrics {
      // implements
      @Override
      double calArea() {
        // ...
      }
    
      @Override
      double calPerimeter() {
        // ...
      }
    }
    

UML Abstract

สัญลักษณ์จะเป็นตัวเอียง

กฏ(s)

  1. ถ้ามี Abstract methods, class จะต้องเป็น Abstract class ด้วย

  2. Abstract class จะไม่สามารถนำไปสร้าง Object ได้

  3. Abstract class สามารถมี methods ธรรมดาได้ จะเรียกว่า Concrete methods

    abstract class A {
       // Concrete methods
       void R() {}   
    }
    
  4. เมื่อแม่เป็น Class ปกติที่มี Methods เปล่าๆ จะเรียกว่า Concrete class

    // Concrete class
    class A {
      void f() {
        // ...
      }
    }
    
    abstract class B extends A {
      abstract void f();
    }
    
  5. สามารถใช้ Abstract class เป็น Type ได้

    GeometricsObject[] geo = new GeometricsObject[10];
    

Interface

  • มีลักษณะคล้าย Class แต่จะมีแค่
    • Constants
    • Abstract methods
  • สร้างมากำหนด Behavior ให้ Object
// Superclass
class Person {
  void eat() {}
  void walk() {}
  void sleep() {}
  void study() {}
}

interface Flyable {
  // constant, cannot change in implemented class
  int flySpeed = 10;
  // abstract methods
  void fly();
}

interface Fightable {
  // abstract methods
  void fight();
}

class SpiderMan extends Person implements Flyable, Fightable {
  public void fly() {
    // bro cannot fly
  }

  public void fight() {
    // bro can fight
  }
}

class Plane implements Flyable {
  public void fly() {
    // bro can fly
  }
}

class FightPlane extends Plane implements Fightable {
  public void fight() {
    // boooomm!
  }
}

interface สามารถ Multiple inherit ได้

interface inf0 {
  void a();
}

interface inf1 {
  void f();
}

interface inf2 extends inf0, inf1 {
  void g();
}

// ต้อง Implements ให้ครบ!
class A implements inf2 {
  public void a() {}
  public void f() {}
  public void g() {}
}

Week 13 GUI

Interface 2

  • ทุกๆ Interface attribute จะมีการใส่ public final static ให้อัตโนมัติ และทุกๆ Interface methods จะมีการใส่ public abstract ให้อัตโนมัติ

Built in interface

  • Comparable

    package java.lang;
    public interface Comparable {
      public int compareTo(Object o);
    }
    
    public class Sting extends Object implements Comparable {
      public int compareTo(Object o) {
        // ...
      }
    }
    
    ✅ new String() instanceof String
    ✅ new String() instanceof Comparable
    
    // เช่นใน Math.max จะรับเป็น Comparable
    public class Max {
      public static Comparable max(Comparable o1, Comparable o2) {
        if (o1.compareTo(o2) > 0) return o1;
        return o2;
      }
    }
    
    String s = (String) Math.max("abc", "abcde");
    
  • Cloneable: Copy object ด้วย clone()

package java.lang;
public interface Cloneable {
}

// เช่น Calendar
Calendar cal = new GregorianCalendar(2003, 2, 1);
Caldendar cal2 = (Calendar) cal.clone();

Shallow vs Deep copy

  • Shallow copy: จะอ้างอิงตำแหน่งเดิม

    House house1 = new House(1, 1750.50);
    House house2 = house1;
    
  • Deep copy: จะสร้างข้อมูลเหมือนกันทั้งหมด ในตำแหน่งใหม่

    House house1 = new House(1, 1750.50);
    House house2 = (House) house1.clone();
    

Interface vs Abstract class

VariablesConstructorsMethods
Abstract classได้หมดมี Constructors แต่ไม่สามารถเอาไปสร้าง Object ได้เป็นได้ทั้ง Abstract หรือ ปกติก็ได้
Interfaceได้เฉพาะต่าคงที่ไม่มี Constructors และนำไปสร้าง Object ไม่ได้ได้เฉพาะ Abstract methods

Graphics User Interface

  • awt (Abstract Window Toolkit)
    • ขึ้นอยู่กับระบบปฏิบัติการ รันที่ไหนจะได้ UI จาก OS นั้น
    • Frame, Panel, Button, Label, TextField, Graphics, Event, ...
  • swing
    • หน้าจอเหมือนกันทุก OS
    • import javax.swing.*;: javax = java extend
    • JFrame, JPanel, JButton, JLabel, JTextField, ...
  • Java 2D
  • Accessibility
  • Drag and Drop

awt and swing

Class ที่สำคัญ

  • Component
    • awt: TextField, Label, Radio, Combo, Button
    • swing: JTextField, JLabel, JRadio, JCombo, JButton
  • Container
    • awt: Frame, Panel, Menu, Dialog
    • swing: JFrame, JPanel, JMenu, JDialog
  • LayoutManager
    • Flow: ซ้ายไปขวา บนลงล่าง
    • Grid
    • Border: ทิศ North, West, East, South และ Center
  • Graphics
  • Color
  • Font

Week 14 Event driven

Event

  • เหตุการณ์ ที่เกิดขึ้นในขณะรันโปรแกรม
  • เช่น
    • เลื่อนเมาส์ จะเกิด MouseEvent
    • กดปุ่ม จะเกิด ActionEvent
    • การพิมพ์ข้อควาใน TextField จะเกิด KeyEvent
  • องค์ประกอบของ Event
    • Event: Object ที่เกิดขึ้นตามประเภทของเหตุการณ์
    • Event source: ตัวที่ทำให้เกิดเหคุการณ์นั้น
    • Event handler: Object ที่ทำหน้าที่จัดการกับเหตุการณ์ผ่าน Methods ของ Event นั้นๆ เช่น Listern ต่างๆ
User actionSource ObjectEvent Type Generate
Click a buttonJButtonActionEvent
Click a check boxJCheckBoxItemEvent, ActionEvent
Click a radio buttonJRadioButtonItemEvent, ActionEvent
Pree return on a text fieldJTextFieldActionEvent
Select a new itemJComboBoxItemEvent, ActionEvent
Window opened, closed, etc.WindowWindowEvent
Mouse pressed, released, etc.ComponentMouseEvent
Key released, presseed, etc.ComponentKeyEvent

Listener interface

  • เป็น Interface ที่คอยรับฟังเหตุการณ์
  • การลงทะเบียนรับ Event กับ Components
InterfaceMethod to listen to event
ActionListeneraddActionListener()
ItemListeneraddItemListener()
KeyListeneraddKeyListener()
MouseListeneraddMouseListener()
......
  • จะต้องมี Methods ที่ต้อง override เมื่อจะจัดการกับ Event
Event ClassListener InterfaceListener Methods (Handlers)
ActionEventActionListeneractionPerformed(ActionEvent)
ItemEventItemListeneritemStateChanged(ItemEvent)
WindowEventWindowListenerwindowClosing(WindowEvent)
(ต้อง Override ให้ครบทั้ง 7)windowOpened(WindowEvent)
windowIconified(WindowEvent
windowDeiconified(WindowEvent)
windowClosed(WindowEvent)
windowActivated(WindowEvent)
windowDeactivated(WindowEvent)
.........
class Listener implements ActionListener {
  public void actionPerformed(ActionEvent e) {
    // ...
  }
}

วิธีการสร้าง Listener

  1. สร้าง Inner Class

    class Ex extends JFrame {
      // Inner class
      class Listener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
          // ...
        }
      }
    }
    
  2. สร้าง Anonymous Listener

    class Ex extends JFrame {
      ex() {
        // Anonymous Listener
        addActionListener(new ActionListener() {
          @Override
          public void actionPerformed(ActionEvent e) {
            // ...
          }
        })
      }
    }
    
  3. สร้าง External Class

    class Ex extends JFrame {
      ex() {
        addActionListener(new Listener());
      }
    }
    
    // External class
    class Listener implements ActionListener {
      @Override
      public void actionPerformed(ActionEvent e) {
        // ...
      }
    }
    
  4. รวมกับ Component ด้วย implements Listener

    class Ex extends JFrame implements ActionListener {
      public void actionPerformed(ActionEvent e) {
        // ...
      }
    }
    

Week 15 Threads

1 Process จะรันได้หลาย Threads แต่จะไม่ใช่การ run แบบ Parallel แต่จะสามารถแบ่งช่วงเวลาเล็กๆ ได้

class ThreadNum implements Runnable {
  public void run() {
    System.out.println("Thread is running...");
  }
}

Thread t1;
t1 = new Thread(new ThreadNum());
t1.start();
class ThreadNum extends Thread {
  public void run() {
    System.out.println("Thread is running...");
  }
}

ThreadNum t1;
t1 = new ThreadNum();
t1.start();

sleep, suspend, resume

  • sleep(ms): เป็นการเปลี่ยน Threads เป็น Blocked แต่จะกลับมา Running เมื่อผ่านไป ms

  • suspend(): เป็นการเปลี่ยน Threads เป็น Blocked

  • resume(): เป็นการเปลี่ยน Threads เป็น Running

    try {
      Thread.sleep(200);
    } catch(InterruptedException e) {}
    

wait, notify

  • wait(): ให้ Thread หยุด
  • notify(): ประกาศว่าพร้อมที่จะทำงานต่อได้แล้ว (ให้ Thraed ทำต่อ)