DEV Community

Codigger
Codigger

Posted on

Blueprints and X-Rays: A Guide to OOP and Reflection in OSE

If variables and functions are the bricks of a program, then Object-Oriented Programming (OOP) is the architectural blueprint that gives those bricks structure and purpose. It's the philosophy that allows us to build complex applications that are modular, reusable, and easy to maintain.
Object Sense (OSE) extends VimL with a complete set of OOP features. Let's explore how to use them to bring your code to life.

Classes and Objects: The Core of OOP

In OOP, a Class is the blueprint, and an Object is the actual thing you build from that blueprint.
You define a class using the Class keyword. A class can contain properties (data) and methods (functions). OSE provides two special methods: Preload(), which runs automatically after the class is loaded, and Construct(), which acts as the constructor to initialize an object's state.
To create an object (an "instance") from your class blueprint, you use the CreateInstance function.

" Create an instance with initial parameters
CreateInstance("Car", #{name: 'BMW'})

" Create a singleton instance (ensures only one exists globally)
CreateInstance('Car')

The Three Pillars of Object-Oriented Design
OOP is built on three fundamental concepts that help you manage complexity.

1. Encapsulation
This is the idea of bundling data and the methods that operate on that data within a single unit (the class). OSE uses the @accessible annotation to control which methods can be accessed from outside the class, hiding the internal implementation details.
2. Inheritance
Inheritance allows a new class to "inherit" the properties and methods of an existing class. OSE supports multiple inheritance using the Inherits keyword. This is a powerful way to reuse code and build relationships between classes. You can also call a method from the parent class using the super keyword.

" Index inherits all methods from both Human and Car
Class Index Inherits Human, Car

" Call the Work method from a parent class
super.Work()

  1. Polymorphism This is a fancy term for a simple idea: different objects can respond to the same message in different ways. In practice, this means a child class can "override" a method from its parent class, providing its own unique implementation. When you call that method on the child object, its specific version is executed.

Reflector: Code That Can Inspect Itself
If OOP gives your code structure, Reflector gives it self-awareness. It’s an advanced capIn this example:ability that allows a program to examine its own structure—classes, methods, annotations—at runtime. Think of it as giving your program X-ray vision.
You can use OSE's reflection capabilities by importing object.Gadget. This allows you to dynamically get information about a class's parents (GetSuperReflectors), its own structure (GetClassReflector), or even the annotations on a class or method (GetAnnotations).
This is incredibly powerful for building flexible plugins and frameworks, as it allows you to write code that can work with other code you didn't know about at compile time.

Putting It All Together: A Practical Example

Let's see these concepts in action. Here is the file structure for a simple project:

|-- oop
|-- Car.ose

|-- Human.ose

|-- Index.ose

And here is the code inside Index.ose, which demonstrates inheritance and polymorphism:

Class Index Inherits Human, Car

" Override the Work method from one of the parent classes
function! s:Work()
    return "override work method"
endfun

function! s:Preload()
    let temp = CreateInstance("Index", "Car")

    " Call the overridden method
    echo temp.Work()

    " Call a method from a parent class using 'super'
    echo super.Stop()
endfun
Enter fullscreen mode Exit fullscreen mode

In this example:
1.The Index class inherits from both Human and Car.
2.It overrides the Work() method with its own version.
3.In Preload(), we create an instance of Index.
4.Calling temp.Work() executes the overridden method from the Index class (Polymorphism).
5.Calling super.Stop() executes the Stop() method from one of the parent classes (Inheritance).
With OOP and Reflector in your toolkit, you can start building applications that are far more structured, maintainable, and flexible. In our next article, we'll cover how to handle errors gracefully to make your code even more robust.

Top comments (0)