I would like to use Moo instead of Moose, but I also need to inherit from non-Moose classes. How should I deal with that? Is there a module to work around this? If not, is there a way I can handle it myself?
Moo can handle subclassing non-Moo/Moose classes already. You don't need an extension.
See the documentation for FOREIGNBUILDARGS, which states:
If you are inheriting from a non-Moo class, the arguments passed to the parent class constructor can be manipulated by defining a FOREIGNBUILDARGS method. It will receive the same arguments as BUILDARGS, and should return a list of arguments to pass to the parent class constructor.
Related
Not sure if I worded this question correctly, but here's my issue: I have a base class and a subclass, and my base class should never be instantiated on its own (in other languages it would be abstract). I know abstract classes aren't a thing in Swift. I have some computed read-only properties that change what they return in each subclass; they are more or less customized constants. Firstly, are overridden computed properties the best way to handle this kind of thing? Secondly, if these variables need to get initialized, i.e. can't be nil, what should they be initialized to in the parent class? Is there a way to otherwise indicate that the parent class shouldn't be initialized on its own?
You probably should use protocol instead of base class in your case. All common implementation can be done in protocol extensions and you won't need to provide default values for constants - just specify required get methods in the protocol.
I want to define global methods.
For that i define their signature under global unit.
What are the disadvantages of doing so ?
Why does it not recommended ?
One disadvantage of using global methods might be that they can be called without explicitly stating the object (just foo() rather than global.foo()), and this is error prone. For example, if your struct happens to have its own method with the same name, such a call is treated as a call to the struct method rather than the global method.
Speaking more generally, one of the principles in object oriented programming is that functions (methods) belong to some object/class rather than being global.
I recommend using sn_utils instead. It is also a singleton like global, but forces you to use its instance name: utils.foo().
You need to be aware not to pollute its namespace, e.g. use <evc-name>_foo() as method name.
Racket's documentation only partially describe what augment and pubment do: augment makes a method that executes after the superclass's version of that method, while pubment makes a method that will implicitly have the augment property if it is defined in a child class.
The docs say absolutely nothing about overment and augride, and I can't guess what they would do based on their names. What are they, and what is the difference between them?
The relatively large family of inheritance functions for Racket's class system is, as you describe, a little confusing, and their somewhat cutesy names don't always help.
In order to understand this, Racket provides two separate mechanisms for method inheritance.
public methods correspond to the classical idea of public methods in other OO models. Methods declared with public may be overridden in subclasses, unless they're declared final, in which case they cannot.
pubment methods are similar, but they cannot be overridden, only augmented. Augmenting a method is similar to overriding it, but the dispatch calls the superclass's implementation instead of the subclass's.
To clarify the difference between overriding and augmentation, when an overridden method is called, the overriding implementation is executed, which may optionally call the superclass's implementation via inherit/super. In contrast, in an augmented method, the superclass's implementation receives control, and it may optionally call the subclass's implementation via inner.
Now, we're also provided public-final, override-final, and augment-final. These are pretty simple. Declaring a method with public-final means it can neither be augmented nor overridden. Using override-final overrides a superclass's public method, but it doesn't allow any further overriding. Finally, augment-final is similar, but for methods declared with pubment, not public.
So then, what about the two weird hybrids, overment and augride?
overment can be used to implement methods initially defined with public. This "converts" them to augmentable methods instead of overridable methods for all the class's subclasses.
augride goes in the opposite direction. It converts an augmentable method to one that is overridable, but the overriding implementations only replace the augmentation, not the original implementation.
To summarize:
public, pubment, and public-final all declare methods that do not exist in a superclass.
Then we have a family of forms for extending superclass methods:
override and augment extend methods declared with public and pubment, respectively, using the relevant behaviors.
override-final and augment-final do the same as their non-final counterparts, but prevent further overriding or augmentation.
overment and augride convert overridable methods to augmentable ones and vice-versa.
For another, fuller explanation, you might be interested in taking a look at the paper from which Racket's model was derived, which is quite readable and includes some helpful diagrams.
Among my two processes' functionality, there is a common function to merge files. I need not going to insist any of the processes to have some methods as interface does. And, also the two processes are independent. So, is it fine I just go with an Abstract class and have the implementation in that abstract class itself? Also I do not need any abstract method.
Inheritance is used when there is IS-A relation between subclass and the base class. I don't think it is the case here. You didn't specify the language, but from your profile I guess you use Java. So if you use an Abstract Class you won't be able to inherit from other, more appropriate class in the future.
Instead of inheritance you can use composition. Which means that you create a regular file merging class which has this method to merge files. And in classes where you want to have this functionality you just instantiate this new file merging class. It lets you inherit from other class in the future.
If you want to inform the world that those classes can merge files (to use polymorphism), and you use Java 8 you can create default method inside an interface and implement this interface without override this default method. But I think composition will be better in this case.
What is the correct way to create an instance from another Moose object? In practice I've seen this done numerous ways:
$obj->meta->name->new()
$obj->new() ## which has been deprecated and undeprecated
(blessed $obj)->new()
-- and, its bastard variant: (ref $obj)->new()
$obj->meta->new_object()
And, then what if you have traits? Is there a transparent way to support that? Do any of these work with anonymous classes?
Of your choices, $obj->meta->name->new() or (blessed $obj)->new() are both the safest.
The way traits are implemented, you create an anonymous subclass and apply the roles to that subclass and rebless the instance into that subclass. This means that either of these solutions will work fine with traits. Perl lacks truly anonymous subclasses (every package has to have namespace), Moose works around this by creating a name in a generic namespace for anonymous classes.
If you'd taken a second to try some example code, you'd see this in action.
$perl -Moose -E'with q[MooseX::Traits];
package Role; use Moose::Role;
package main; say Class->with_traits(q[Role])->new->meta->name'
MooseX::Traits::__ANON__::SERIAL::1
Hope that helps.