|Welcome to the Monastery|
Too bad you are teaching people bad habits. I know using a hash reference to store you attributes in is common, but it's bad habit. Here on perlmonks, people scramble over each other if someone dares to post code that doesn't use 'strict' to scold at the person for not using strict.
Using hashes to store object attributes in is like writing non-OO code using global variables, no package names and certainly no strict. You're loudly declaring that you don't want the benefits of stricts, namespaces or scoping. On top of that, you're tossing one of the pillars of OO programming out of the window: encapsulation. You're not taking any steps to prevent hiding your implementation - it's even worse, you are forcing the classes that inherits you to adapt your implementation.
Let's look at some issues. Suppose we have an class, Animal whose instances have an attribute, species. We write two accessor methods, get_species and set_species:
This code compiles fine. No matter how many warnings and strictness you have turned on. It will even run fine, at best you get somewhere down the line a warning that you are using an undefined value. The equivalent non-OO code wouldn't even compile with strictness turned on.
Same typo, but a compile time error.
And here's how you are not using proper encapsulation. Suppose you have a generic Document class. The generic class gives you some minimal functionality, like adding and deleting text. Suppose that the class wants to track the number of lines in the document. It's an attribute that's only used in this class, so it's even using the "convention" to put an underscore in front of the attribute name. The number of lines is stored in the attribute _lines. Now we subclass the generic class to create a LaTeX class, for LaTeX documents. As part of the functionality, we also keep track of the amount of lines of the generated dvi output. Since this will be a private attribute as well, we use _lines as attribute.
DONG DONG DONG! That will give problems. Sneaky problems, that won't be detected at compile time - and not even give warnings at run time, no matter how many warnings you turn on. Perl gives you name spaces, and scopes, but you aren't using them, not even in an OO program where encapsulation is one of the key elements.
Note that you have a similar problem in your code when you are using the underscore convention. You call _open as a method. Which means that if there's an inheriting class that uses the same convention, you call the subroutine in the class, not your own. Better call it sub as a sub, not as a method. Why would you? It's intended to be a private method, so you don't want to call an inherited method anyway.
The bottom line is, if you want to use object oriented programming, you're better off using a language designed by someone who understood the concepts of object orientness. And not a language that found a cute trick to use arrows.