marked and unmarked class in pharo 2.0 smalltalk - smalltalk

i need to implement the message markedSubclass in pharo that works just like subclass but i need the class that gets created to be somehow marked,for example i tried adding a unique instance variable to it after creating it but it's just not working,maybe i'm adding it to a wrong place.
the requirments are:
every subclass of this marked class should also be marked even if it
was created via subclass (not markedSubclass).
other than that a marked class should function just as a regular class should.
any help would be appreciated.
example:
User markedSubclass: #MarkedUser
User subClass: #UnmarkedUser
MarkedUser subclass: #MarkerUser2
i need to somehow know that MarkedUser and UnmarkedUser are both marked classes.
what i thought of lately is adding the method "isMarked" to Class class and this way all
the classes will have it, and each class will override it accordingly so if we write
User class isMarked.
it will return false but if we write:
MarkedUser class isMarked.
MarkedUser2 class isMarked.
it will return true for both.
but where can i add this method?and how can i make a class override the method in runtime?

Add a class method like the following to your User class:
markedSubclass: className
| subclass |
subclass := self subclass: className asSymbol.
subclass class compile: 'isMarked', String cr, String tab, ' ^ true'.
^ subclass
Then try in a workspace:
User markedSubclass: 'MyMarkedSubclass'
Add an #unmarkedSubclass: class method accordingly.
You could then override the general #subclass: method in your User class to set the same marker as the receiver.

Related

Why don't I need to write property at object class in sealed class by Kotlin?

I'm developing the app by using Kotlin.
sealed class DestinationScreen(val route:String){
object Signup: DestinationScreen(route = "signup")
}
#Composable
fun InstagramApp(){
val navController = rememberNavController()
NavHost(navController = navController, startDestination = DestinationScreen.Signup.route){
composable(DestinationScreen.Signup.route){
SignupScreen(navController = navController)
}
}
}
I don't know Why Signup singleton class can have the property "route" using argv?
I understand it inherits DestinationScreen. So it also has route property.
But Destination class doesn't have concrete the property route.
If Destination class is data class, make sense it doesn't need to declare the property.
No need for{}. And data class has the property not declareing it by using argv.
So I mean DestinationScreen should has concrete property route, if Signup inherit different property's value, it should override.
Why can this codes above work? Does this feature have seal class or object class?
Please teach me. Thank you.
But Destination class doesn't have concrete the property route
Yes, it does. The route property is declared right there in its constructor.
if Signup inherit different property's value, it should override
Not sure what you mean by this, but Signup doesn't need to override the property. It already inherits the property. By passing a value to the super-class's constructor, the existing property gets an initial value as passed by the sub-class without overriding it.
You mention sealed and data class types, but they are irrelevant to this discussion. Inheritance works the same way with sealed and non-sealed classes.
Any time a class extends another class, it also is a type of that class and inherits all of its properties and functions, no overriding needed.

Is it possible to determine the type of a class at instantiation or convert the type afterwards without casting?

For example: I have some classes that all inherit from the same class.
Public Class MasterClass
' content
End Class
Public Class ClassA
Inherits MasterClass
'content
End Class
Public Class ClassB
Inherits MasterClass
'content
End Class
Public Class ClassC
Inherits MasterClass
'content
End Class
And I want decide on runtime which one I need. Then I can do something like this:
Private myInstance As MasterClass
If conditionA Then
myInstance = New ClassA
ElseIf conditionB Then
myInstance = New ClassB
Else
myInstance = New ClassC
End
But it can get quite long, and I still have to cast it evertime I use it.
I can assing a type to a variable, but I don't know how to use that type to create a new instance of that type..
Dim storedType As Type = GetType(ClassA)
Dim someInstance = New storedType 'Does not work
Is there a better way? Can you change the type of a variable at runtime?
I still have to cast it evertime I use it.
The idea around polymorphism and inheritance is that you don't have to cast them to use them. You can write things in such a way that the master class has all the functions etc that you need (whether or not they do anything) and then you call things as if you were just dealing with the master class but, because each child implements a different behavior, the end result is different - your program might not even know (if the child implementation came from a third party dll) what is going on but it doesn't matter
Can you change the type of a variable at runtime?
Sure, but you have to use it how it appears. Long chains of "if my object is an instance of x then cast my object as x and use method X1, else if my object is a y then cast as y and call y1" are not polymorphic/not leveraging inheritance principles properly - you're supposed to call myobject.whatever, and if my object is an x, then x1 happens and if it's a y then y1 happens
I want decide on runtime which one I need
But you don't have to do that in the class that knows about class a/b/c - each of class a/b/c can do that and hence become self contained. You can have all your instances in an array of the parent type, and visit each one asking them if they handle the condition and use the one that says it can
Consider a slightly better real world example than this artificial class a/b/c trope:
You are tasked with writing an app that can download an image (png, jpg or gif) from somewhere (http or ftp or disk location), rotate it and upload it to somewhere else
You decide to have an ImageRotator parent that specifies a CanHandle function and a Rotate function. It has 3 subclasses, one that handles jpg, one that rotates gif and one that does png. When presented with a PNG filename the JpgRotator says No when asked if it can handle it etc.
Separately you have a FileMover parent that CanHandle and has Download/Upload functions. Again, the parent doesn't implement these at all. The three subclasses implement the ability up/down an http, an ftp and a disk location
You create an instance of each rotator and put it into an array of ImageRotator type. You also create an instance of each mover onto an array that is a FileMover parent type.
Your user specifies a jpg in a http url, and to store it in a disk location at the end. You loop your FileMovers and ask each if they support the location the user provided. The http mover says yes, you invoke its download to a temp path. Then you pass he path to each rotator, the jpg rotator says yes, you call rotate. Finally, you look for another mover that can handle an output path of local disk...
Someone decides to extend your program with a plug-in dll that adds he ability to put files in and out of a db, and support tiff images.. ignoring the magic of how instances of their classes come to be in your arrays, you can see that your program can now move these new locations and types because the logic for whether they handle db/tiff is not a part of your code.. your code just treats everything consistently
In this case Interfaces are the best choice
Interface ABC
Property Text As String
Property Value As Integer
End Interface
Public Class MasterClass
End Class
Public Class ClassA
Inherits MasterClass : Implements ABC
Property Mystr As String Implements ABC.Text
Property Sum As Integer Implements ABC.Value
End Class
Public Class ClassB
Inherits MasterClass : Implements ABC
Property MyText As String Implements ABC.Text
Property Value As Integer Implements ABC.Value
End Class
Public Class ClassC
Inherits MasterClass : Implements ABC
Property str As String Implements ABC.Text
Property Value As Integer Implements ABC.Value
End Class
usage
Dim myABC As ABC
If conditionA Then
myABC = New ClassA
ElseIf conditionB Then
myABC = New ClassB
Else
myABC = New ClassC
End If
myABC.Text = "Interface"

Is subclass: an ordinary method in Squeak?

It seems that creating a new subclass in Squeak is done by sending a message to the super class:
Object subclass: #Boolean
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'Kernel-Objects'
Where can I look at the implementation of this method? I can't find it in Object's nor ProtoObject's class methods list.
Yes it is an ordinary message. The implementation is in the class called Class. You can find its implementation by selecting the message name in any class definition (like the one you posted in the question) and invoke the "implementors of it" action (Cmd-m, or in the pop up menu if you hold shift while clicking).
You will find that it delegates to ClassBuilder, where you can see how new classes come into existence.
Note that you send the message to the class Object, not to an instance of Object. That's why you did not find a method in Object or ProtoObject. You would rather have to look up the method in Object class, which is the metaclass of Object, and it inherits from Class.

groovy method scope when using a method reference

I have a groovy class that looks up a method reference and then invokes it. The method being invoked is a private method. When the actual class is an instance of the child class, it throws an error that it cannot find the private method, even though it is the public method in the parent that actually calls it.
In this case, I could obviously just call pMethod2() directly and that works, but I'm trying to understand why this doesn't work as written and if there's a way to correct it so it works.
class Parent {
def pMethod1() {
def m = this.&pMethod2
m() // this call fails if the calling class is of type Child
}
private def pMethod2() {}
public static void main(String[] args) {
new Child().pMethod1();
}
}
class Child extends Parent {}
It is a bit confusing, especially if you're used to C / C++. What you get when using the ".&" operator in Groovy is not an address, but an instance of MethodClosure.
The MethodClosure object contains an owner and a delegate object, which is used when resolving the method to call. In your example, the owner and delegate object will be "this", which is an instance of Child. The method to call is simply stored as a string.
So, the assignment
m = this.&pMethod2
is just a shorthand way of writing
m = new MethodClosure(this, "pMethod2")
When you invoke the m() closure, it will try to resolve (at runtime) the method by looking for methods named "pMethod2" in the owner and the delegate objects respectively. Since the owner and delegate is an instance of Child, it will not find private methods located in Parent.
To make your example work you must make sure that the method is visible to the owner and/or delegate of the closure.
This can be done several ways, for instance by changing the access modifier of pMethod2 to protected, or by creating the closure with an instance of Parent; something like this:
m = new Parent().&pMethod2
Note that is is irrelevant that you created the MethodClosure instance in a method where pMethod2 is actually visible. It is also irrelevant that you invoke the closure in a method where it is visible. The method is not visible to the owner or delegate of the MethodClosure, which is what is being used when resolving the method.

MyBase can not to be used in a Extension Method?

I created a module to add some Extension Methods to a Class.
This Class inherits from another parent Class.
In the code of my Extension Methods, I would like to refer to the base Class using MyBase.
This doesn't seems to be allowed (Error message : "'MyBase' is not valid within a Module.")
<Extension()>
Public Function Get_OutOfSpace(val as ClassA) As Boolean
Return MyBase.IsOutOfSpace()
End Function
How can I invoke a method of my base class within an Extension Method?
That's why they force you to write extension methods in a module, so you can't make the mistake of using MyBase. But there's at least one other thing wrong with your code, you didn't extend anything. The first argument of an extension method must be a reference to the object, of the type you want to extend:
<Extension()>
Public Function Get_OutOfSpace(ByVal obj As Foo) As Boolean
''...
End Function
So a likely implementation is Return obj.IsOutOfSpace. Which in turn makes it very likely that you don't actually have any use at all for this extension method since the class you want to extend already has an IsOutOfSpace property.
Only use extension methods to add methods to classes. And only do so if you can't change the class.