Is it possible to abstract away the subject type in the declare parents statement? - aspectj

Consider the following abstract aspect:
public abstract aspect LoggingAspect {
declare parents: (#LogMe *) implements ILoggable;
...
}
Is it possible to abstract (#LogMe *) away, behind a type pattern declaration, that could be overridden in a derived aspect?

The best thing I can think of is to do something like this:
keep the abstract LoggingAspect as is
in the concrete sub-aspects use declare #type to add the #LogMe annotation where you need it to go.

Related

Why can't the parameter type of a #override method be “tighten” in Dart?

Background
I am new to Dart and recently I've been reading some docs about Dart sound type system until I ran into a section called Use sound parameter types when overriding methods
It states that
The parameter of an overridden method must have either the same type
or a supertype of the corresponding parameter in the superclass. Don’t
“tighten” the parameter type by replacing the type with a subtype of
the original parameter.
and shows me a block of code saying
What I am confused of
My question is that, of course, by prohibiting parameter type "tighten" in an override method we can prevent
define a cat and send it after an alligator
class Animal {
chase(Animal a) {}
}
class Mouse extends Animal {}
class Alligator extends Animal {}
class CatA extends Animal {
#override
// error on this line
void chase(Mouse x) {} // It makes sense. Cat chases Mouse
}
class CatB extends Animal {
#override
// error on this line
void chase(Alligator x) {} // Cat chases Alligator ? You can't be serious!
}
But how about using a Object(witch is the supertype of almost all others) as its parameter type
class Cat extends Animal {
#override
void chase(Object x) { // Now this Cat can chase anything.....
}
}
void main() {
var cat = Cat();
cat.chase(Alligator()); // Again, we are trying to let a little pussy chase a terrifying beast!
}
// This piece of code works
What is it all about, this does not makes sense to me at all...Furthermore, what if I create a supercat that extends a Cat, which can indeed chase after a Alligator
class SuperCat extends Cat {
#override
// error on this line
void chase(Alligator x) { // I make a SuperCat chasing after a Alligator intentionally, but it doesn't work...
}
}
These things above are really blowing my minds off, do I get it wrong in some way or is there anything more under the hood that makes it this way?
Update
Thanks to #jamesdlin and #Abion47, I could finally figure out most of the puzzles, but there is still one more problem to solve. As #jamesdlin mentioned, contract of the base class method must be honored when overriding a method. Taking Animal and Cat for example, Animal.chase makes a contract saying chase must be compatible to accept any Animal, no matter it is Alligator or
Mouse, but does this contract also make a restrction that chase must not be able to accept any other Object excepts for Animal?(It is natural to think about it because you can't pass a casual Object parameter into Animal.chase) And if it does, why does Dart allow widening Cat.chase parameter type from Animal to Object? Doesn't it violate the contract made by Animal.chase?
The answer referenced by jamesdlin has the details of why this isn't allowed, but I'll try to give a nutshell version.
abstract class Animal {
void chase(Animal a) { ... }
}
class Mouse extends Animal {}
class Alligator extends Animal {}
class Cat extends Animal {
#override
void chase(Mouse x) { ... } // No-no
}
In theory, this would be fine, since Mouse extends Animal and Cat is just restricting what kind of animal can be passed to chase.
But think about what happens with polymorphism. The hard rule is that any classes that extend and override a base class must be compatible with that base class. That ensures that, even if the function is called on a handle that is typed to the base class, it is guaranteed that the call will go to the correct function definition in the overriding class.
This is what makes abstract classes possible - if there was an implementation of a function in a derived class that wasn't compatible with the same function in the base class, it would be impossible to treat instances of inherited classes as though they were instances of the base class.
For example, take the example from the article but instead of explicitly creating a Cat, have it be some randomly generated animal:
Animal a = RandomAnimalFactory.create();
a.chase(Alligator());
What is the exact type of a? You have no way of knowing. All you know is that it is some subtype of Animal.
Now look at the call to a.chase(Alligator()). Would that succeed? Well, yes, because Animal.chase requires an Animal and Alligator is an Animal. No problems there.
But imagine if a subclass could restrict the type of that parameter, e.g. if Cat could restrict it to Mouse. Now it's unclear whether that call would succeed because even though you know that a is an Animal, you don't know what kind of Animal. What if it's a type that makes Alligator no longer a valid parameter? In order to know, the type system would have to unpack the declared type of the variable to examine the actual type, and only then would it know whether the call would succeed. This flies in the face of inheritance, where a type that extends a base type can be interchangeable with any of its sibling types.
All of a sudden, what used to be a simple matter has become extremely complex. Not only does it make the implementation of an OOP-based type system astronomically more complicated, it completely undermines the point of inheritance.

How to explain the following sentences about private[this] and variance?

In Chapter 19 ,"Programming in scala 2nd edition",how to explain the bold sentences ?
object private members can be accessed only from within the object in
which they are defined. It turns out that accesses to variables from
the same object in which they are defined do not cause problems with
variance. The intuitive explanation is that, in order to construct a
case where variance would lead to type errors, you need to have a
reference to a containing object that has a statically weaker type
than the type the object was defined with. For accesses to object
private values, however,this is impossible.
I think the most intuitive way to explain what Martin is trying to say is to look at arrays in Java. Arrays in Java are covariant but don't type check according to covariance rules. This means they explode at runtime instead of compile time:
abstract class Animal {}
class Girafee extends Animal {}
class Lion extends Animal {}
public class Foo {
public static void main(String[] args) {
Animal[] animals = new Girafee[10];
animals[0] = new Lion();
}
}
The fact that I can do this is because:
Java doesn't restrict this at compile time (due to a design decision)
I have a reference to the underlying array which allows me to manipulate it's internal values
This doesn't hold when talking about private fields of a class from the outside.
For example, assume the following class:
class Holder[+T](initialValue: Option[T]) {
private[this] var value: Option[T] = initialValue
}
When creating an instance of Holder, I am not visible to it's internal fields, thus I cannot manipulate them directly like I did with the Java array. This way, the compiler makes sure they are protected, and each manipulation to the field will have to be through a method, where the type checker is strict and doesn't allow funky business.

Scala: Using self types to implement a strategy pattern

I'm attempting to implement a strategy pattern for a class I have that manages state. The strategy implementations should have access to the protected/public members of the class which uses those strategies, and the class using the strategies needs access to the public members of the strategy.
I've got this working, except I can't really figure out how to do this without creating different top-level classes per-strategy. Here is an example:
class BranchState(a: String, b: Int) extends ABranchState(a, b) with QueuedStrat
class ABranchState(a: String, b: Int) {
this: ChainingStrategy =>
.... lots of impl ....
}
trait ChainingStrategy {
self: BranchState =>
... headers only, no impl ...
}
trait QueuedStrat extends ChainingStrategy {
self: BranchState =>
.... impl ....
}
trait AnotherStrat extends ChainingStrategy {
self: BranchState =>
.... impl ....
}
The problem here is if I want to instantiate a BranchState with uses AnotherStrat, I have to make another class. I've tried to add a type parameter to BranchState like [T <: ChainingStrategy] but that doesn't work because the compiler (rightfully) complains I have to have implementations for the headers in ChainingStrategy. It seems like I need some mechanism to say "some type which implements chaining strategy fully, IE: has no unimplemented methods".
Maybe that's just not the right way at all, though. How can I accomplish this?
Thanks
I don't think what you are trying to do does make any sense in term of design. You are trying to treat your strategies as if they were states. But a Strategy is not any specialization or generalization of a State, so I don't think they should have any inheritance relationship.
Moreover, in Scala one should not be needing the Strategy Pattern, due to the functional aspect of the language, you could take a real advantage of Higher-order Functions (I recommend you to read: How Scala killed the Strategy Pattern, Alvin Alexander).
I hope this helps you!

companion object to a private class: why isn't it valid?

i needed two instances that has access to each other privates. i naturaly thought of a companion object that grants access to a one and only instance of it's companion class. the class itself i made private, so users cannot just create instances using new.
object A {
def apply = dual
lazy val dual = new A
}
private class A {
//some irrelevant logic...
}
this code does not compile. i get: class A escapes its defining scope as part of type A error, which i don't really understand. my current workaround was to define a trait with every method declaration the class should have and make class A extend that trait, while dual is of the trait type, and not class A type.
what's the theoretic problem i'm missing here? why is this forbiden?
Paolo's solution is good (+1), but he didn't explain the error message, so let me try that. The problem stems from the fact that every method needs a return type. Your original definition of apply and dual returned an object of class A, thus the implicit return type of both was A. That implies that A must be visible to clients - how else could they call the function or access the val? Moreover, as both - and their parent object too - are public, they are globally visible. However, you declared A private which means it must not be visible outside its package. So there is a conflict which can't be resolved by the compiler.
The general rule is that all parameter and return type of functions / members must have (at least) the same scope of visibility as the referring member itself*. Thus one trivial way to solve this problem would be to reduce the visibility of apply and dual to private. This would satisfy the compiler, but not you :-)
Your solution gets around the problem by changing the static return type to a public trait, which thus has the same visibility as the members referring to it. The dynamic type of the returned object is still class A, however, this need not be visible to clients. This is a classic example of the principle "program to interfaces, not implementations".
Note that to apply this principle to the full extent, one could turn class A into a private inner class of object A, thus making it innaccessible even for other classes within the same package:
trait A {
//...
}
object A {
def apply: A = dual
lazy val dual: A = new AImpl
private class AImpl extends A {
//some irrelevant logic...
}
}
* To be pedantic, the enclosing class / object may reduce the visibility of its members, like here:
private class Holder {
def member = new Hidden
}
private class Hidden
where member is public but its enclosing class is private, effectively hiding its members from the external world. So the compiler emits no complaints here.
I think you don't want a private class, but a class with a private constructor.
class A private()
object A {
def apply = dual
lazy val dual = new A
}
Now your class is "visible" to outside code, but only your companion object can create instances of it.

Scala type parameters recurrence

In Scala you can define parameters that descend from other one that take the first one as parameter. For example in Lift you can find such things in Record and Mapper
MongoMetaRecord[BaseRecord <: MongoRecord[BaseRecord]]
What does it mean and how is that useful ?
This is a pattern often used to let an abstract class know about the type of the actual concrete class that extends it. It is sometimes useful to know what that final concrete type is — for instance, to use it as the return type of a method that produces a copy of the current object.
Suppose you want to do this — let an abstract class Abstract know about the concrete type implementing it. You could start by defining a type parameter, maybe like this:
trait Abstract[A] {
def copyObject: A = ...
}
But then you realize that actually, A should be a subclass of Abstract itself, as you don't want subclasses to provide a random parametrization. So you could add this:
trait Abstract[A <: Abstract]
... but you'll soon realize that Abstract has turned into a generic type as well, so you'll rather need this:
trait Abstract[A <: Abstract[A]]
As a final step, you'll probably want to make A covariant if you can, so as to allow intermediate abstract classes along the inheritance path from Abstract to the final concrete class:
trait Abstract[+A <: Abstract[A]]
class Concrete1 extends Abstract[Concrete1]
trait RefinedAbstract[+A <: RefinedAbstract[A]] extends Abstract[A]
class Concrete2 extends RefinedAbstract[Concrete2]
This means that every non-leaf (abstract) type should be parametrized, and that only the final concrete class will be able to drop the type parameter.