In the last part we've shown how to create and use a class in Python. Today we're going to talk about inheritance: wchich means creating sub-classes, which add different behaviour to the class they inherit from (or extended class, in Java nomenclature).
Suppose we have a class like this:
classRunner:
def__init__(self):
self.shoes = True
defhasShoes(self):
returnself.shoes
We can create an object of this class and call the method hasShoes on it:
# !/usr/bin/python3
classRunner:
def__init__(self):
self.shoes = True
defhasShoes(self):
returnself.shoes
defmain():
myRunner = Runner()
print(myRunner.hasShoes())
if __name__ == "__main__":
main()
The code results in:
True
Now let's extend this class by creating a subclass (LongDistanceRunner) and adding a method there - and let's create an instance of subclass and call this method:
# !/usr/bin/python3
classRunner:
def__init__(self):
self.shoes = True
defhasShoes(self):
returnself.shoes
classLongDistanceRunner(Runner):
defrun(self):
ifself.hasShoes():
print("Running slowly")
else:
print("Not running (no shoes)")
defmain():
myRunner = Runner()
print(myRunner.hasShoes())
ldRunner = LongDistanceRunner()
ldRunner.run()
print(ldRunner.hasShoes())
if __name__ == "__main__":
main()
The code results in:
True
Running slowly
True
As we can see, we can call both run() - which is method from the subclass (LongDistanceRunner) and hasShoes() which is method defined in superclass ( Runner ) on the object of class LongDistanceRunner. What' more - in the class LongDistanceRunner (in the method run() ) we can use our superclass features (in this case: the method hasShoes() ).
Now let's add another class inheriting from Runner:
# !/usr/bin/python3
classRunner:
def__init__(self):
self.shoes = True
defhasShoes(self):
returnself.shoes
classLongDistanceRunner(Runner):
defrun(self):
ifself.hasShoes():
print("Running slowly")
else:
print("Not running (no shoes)")
classShortDistanceRunner(Runner):
defrun(self):
ifself.hasShoes():
print("Running fast")
else:
print("Not running (no shoes)")
defmain():
myRunner = Runner()
print(myRunner.hasShoes())
ldRunner = LongDistanceRunner()
ldRunner.run()
print(ldRunner.hasShoes())
sdRunner = ShortDistanceRunner()
if __name__ == "__main__":
main()
We can add both our "runners" to a collection and call the method hasShoes() on both of them:
# !/usr/bin/python3
classRunner:
def__init__(self):
self.shoes = True
defhasShoes(self):
returnself.shoes
classLongDistanceRunner(Runner):
defrun(self):
ifself.hasShoes():
print("Running slowly")
else:
print("Not running (no shoes)")
defdrinkWater(self):
print("Drinking water (while running)")
classShortDistanceRunner(Runner):
defrun(self):
ifself.hasShoes():
print("Running fast")
else:
print("Not running (no shoes)")
defdrinkWater(self):
print("Drinking water (not while running)")
defmain():
myRunner = Runner()
print(myRunner.hasShoes())
ldRunner = LongDistanceRunner()
ldRunner.run()
print(ldRunner.hasShoes())
sdRunner = ShortDistanceRunner()
runners = [ldRunner, sdRunner]
print("Do runners have shoes?")
forrunnerinrunners:
print(runner.hasShoes())
if __name__ == "__main__":
main()
Which results in:
True
Running slowly
True
Do runners have shoes?
True
True
What's interesting here is that the hasShoes() method works "polymorphic" here - although it's not defined in the superclass. This behaviour is what differs polymorphism in Python from Java, C# or C++ - in all these languages polymorphism is strictly connected to inheritance.
Today we'll take a look at some examples of object-oriented code in Python.
As I'm learning this topic almost in the same time I'm writing this, I'll do lot of mistakes - especially because some topics seem different than C++/Java/C# style I'm used to.
Ok, let's begin with creating a class with one method, creating an object of this class and calling this method.
# !/usr/bin/python3
classClassWithMethod:
defsay_something(self):
print("Elementary!")
defmain():
objectWithMethod = ClassWithMethod()
objectWithMethod.say_something()
if __name__ == "__main__":
main()
We define a class ClassWithMethod, with one method: say_something(self) simply printing some text. self param is, as we will see, the reference to the calling object. For now, we just instantiate the class:
objectWithMethod = ClassWithMethod()
...and call the method:
objectWithMethod.say_something()
The result of running this code is:
Elementary!
Now let's define other class with one field (or attribute).
classClassWithField:
def__init__(self, name):
self.name = name
To instantiate and use it we can add the following lines to main function:
objectWithField = ClassWithField("Lestrade")
print(objectWithField.name)
As we can see, __init__(self, name) works as a constructor with one parameter. The code now prints:
Elementary!
Lestrade
What about a method? Well, take a look at another class:
classClassWithFieldAndMethod:
deftellName(self):
print(self.name)
If we instantiate it, and set field name to something, we can call our method (in main!):
We create another object (objectWithFieldAndMethod2), add the field named age to it (simply by initializing it) and then we can access it. The code execution result becomes:
Elementary!
Lestrade
John Watson
Sherlock Holmes
33
Please note we've added the age field to our object, not class. It means that if we try to get to this field on our previous object, we get error.
BUT in fact, we can access this field - as "private" in Python does not mean the attribute is unaccesible - it rather means it should not be accessed. So we can access this attrbute using the following syntax: objectName._ClassName__field_name (please note the underscores, one before class name and two before field name):
The last thing: static (class) fields. They're defined simply in class body, not in the methods:
classClassWithStaticField:
field = 40
But beware: they can be accessed with both class name and object name. In the first case, they behave like static. In hte latter - they're simply fields, initialized with given value.
An example should give us more light on this:
stat1 = ClassWithStaticField()
stat2 = ClassWithStaticField()
stat2.field = 41
print(stat1.field) # object's field default value is 40
print(stat2.field) # this object's field value is 41
print(ClassWithStaticField.field) # static field value is still 40!
... which code gives us:
40
41
40
40
We create two objects of class ClassWithStaticField, stat1 and stat2. Then we assign value 41 to the field field of the first object. It changes this instance's value, but the field field of object stat1 stays the same! What's more - the ClassWithStaticField.field is also another reference. We can change it, of course, by calling:
ClassWithStaticField.field = 42
So the code:
stat1 = ClassWithStaticField()
stat2 = ClassWithStaticField()
stat2.field = 41
print(stat1.field) # object's field default value is 40
print(stat2.field) # this object's field value is 41
print(stat1.field) # object's field default value is 40
print(ClassWithStaticField.field) # static field value is still 40!
ClassWithStaticField.field = 42
print(ClassWithStaticField.field) # not anymore!
results in:
40
41
40
40
42
Confusing? Well, for me it certainly is ;D The full program listing illustrating the concepts above looks as follows:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This time again we're going to be talking about something available in Kotlin, but not in Java: operator overloading.
Operator overloading means that we can apply operators, like + (someobject+anotherone) or [ ] (someobject[5]) to our objects. Expression like this (someobject + anotherone) can be thought of as methods: it's just another way of expressing someobject.plus(anotherone). someobject[5] would mean "call the method [] with parameter 5 on someobject.
Altough operator overloading is an old concept (it's common in C++, where - for example - the famous cout<<"Something"; actually uses overloaded left bit shift operator for object cout of class ostream; it's also available in C# and Python), it's not implemented in Java (which was a deliberate choice of its creators).
Still, it can be very useful and Kotlin allows it.
Let's get to our code. I think the most basic example of operator overloading is use of class representing complex numbers (the code below is the full program, with both class definition and it's use):
package com.mypackage
import kotlin.Exception import kotlin.math.sqrt
class Complex(var re: Float, var im: Float){
fun modulus(): Float{ // just a method return sqrt(re*re+im*im) }
// "this" can be omitted operator fun plus(another: Complex): Complex{ // a+b return Complex(this.re+another.re,this.im+another.im) }
operator fun minus(another: Complex): Complex{ // a - b return Complex(re-another.re, im-another.im) }
operator fun times(another: Complex): Complex{ var resultRe = re*another.re-im*another.im var resultIm = re*another.im+im*another.re return Complex(resultRe, resultIm) }
... which defines the class Complex representing a complex number, and overloads the infix "+", "-", "*", comparison (<, >, >=, <=) and [ ] operators. There is also modulus function, which is just a method... And which we use to define our overloaded comparison operators behaviour (operator fun compareTo).
The execution of the code above results in the following output:
multiplied:(80.0,15.0)
(2.0,0.0)
(2.0,0.0)
2.0
true
true
We can see that my implementation of complex multiplication is correct ;)
The +, -, * operators, implemented as plus,minus, and times are quite self-explanatory: they take one parameter, and use this.re and this.im (or just re and im) of current (left to operand) values to compute the results, which they return.
In order to override them, we use operator keyword before a method definition. Please note they can be called both as operators ( val sum = c+c2 ) or just as methods ( val sum2 = c.plus(c2)).
In comparison operator overload (operator fun compareTo(another: Complex)) I've used previously defined modulus method, because there is no unequivocal way of comparing complex numbers - so I compare their moduli. This operator should return -1 if the first operand is "smaller" than second one (in our case it's modulus is smaller), 1 if it's "bigger" and and 0 it they're the same.
I've also overloaded get operator, which affects suqare brackets, like in the call println(sum[0]). What it does, is simply return real part of our complex as 0-th element and the imaginary part as 1-st one. If called with something else than 0 or 1, it would throw IllegalArgumentException(). Typically this operator would be used for some class representing collection (like list - please note in Java you'd have to use somelist.get(i) instead of just somelist[i] to get i-th element of the somelist List or like text string, where it would return n-th character).
There are other operators to overload, like not (!) - but I simply can think of no use of it regarding complex numbers :). When you type operator fun (with the spacebar after the word fun) and hit Ctrl+Space in IntelliJ Idea or Android Studio, you'll get the full list of the operators possible to overload with their symbols on the right and corresponding keywords (like plus or minus in the example above) on the left:
Please note compareTo does not affect == comparison effect: that's what overriden function override fun equals(other: Any?) does.
A word on Java - of course, lack of operator overloading in Java doesn't mean we could not implement a class Complex in this language. We can, of course. But the only way of representing "sum of complex1 and complex2" would be some function or method, like complex1.add(complex2) or maybe sum(complex1, complex2) - not the intuitive and obvious Kotlin's complex1+complex2.
Well, that would be basics. More details, including the full list of operators available for overloading in Kotlin are available in the Kotlin's documentation.
Today I'm not going to use the format typical for this series, instead - I'll just show you two features of Kotlin I've just learned about. As there are no named arguments and default parameter values in Java, I cannot provide you the Java code counterpart this time :)
The function divide has (quite obviously) two arguments: nominator and denominator. If you call the function without specifying their names, their order matters: in our case, the first argument is divided by second one.
But... You can also call our function with named parameters: as in Python, here also it means you can switch their order (the calls initializing result2 and result3.
And second thing: also exactly as in Python, the parameters in Kotlin can have default values.
So that the following code, for example:
fun power(base: Float, exponent: Float = 2.0f): Float{ return base.pow(exponent) } fun main() {
val a2cubed = power(10f,3f) var a2squared = power(10f)
println(a2cubed) println(a2squared) }
... makes power function actually a square function, when called with just one argument.
The code above produces the following result:
1000.0
100.0
I think that's all for today. Both named parameters and default values are neat features - especially in functional language - and another advantage of Kotlin over Java - it's good to know they're available.
If you have lot of assets in your project, and multiple scenes in particular, it can be hard to navigate between them.
I've encountered two basic problems while working in Unity:
1) doing something (or checking something) in multiple scenes
2) running a particular scene which is required to run for your game (for instance, it loads all assets), while working on another one.
This is where editor scripts come to the rescue :)
In the following code I'll show how to create a tool for iterating over enabled scenes (and logging their root count object as an example), and another - for simply running some chosen scene.
Create a file ScenesHelper.cs and put it in Assets/Editor folder of your project.
The method GetEnabledScenes() returns all enabled scenes (by omitting the Where clause you can also include those not enabled), or to be precise - objects of class EditorBuildSettingsScene , which represents scenes "identifiers" in editor build settings.
The method GetEnabledSceneNames() returns their paths/names (retrieved via LinqSelect).
Then we have the method Iterate() (available from the Tools menu or via Ctrl+Shift+P shortcut) which iterates over all the enabled scenes (using their names) and logs the root objects count for each of them, and PlayScene2() (Tools menu or Ctrl+Shift+O) which makes the editor play the second scene in our list.
Please note opening a scene in Iterate() uses Scene class object, returned by EditorSceneManager.OpenScene(s) - it's not the same as EditorBuildSettingsScene. The former represent Unity scenes with objects, which can be inspected or played, the latter is sort of id of a scene in editor build settings.
Today something different. The problem I’ll write about is: how
to make a Windows Forms (C#) app minimize to tray when cliked on „X”
and prevent it from displaying in the taskbar.
In other words – how to make a „typical tray app”.
To be honest – I was quite sure there would be some component
(control) for it.
And there is (NotifyIcon) but… It’s not enough just to drag it to
our app designer form in Visual Studio to make it work as we would
like to.
Let’s begin with
opening Visual Studio and creating a new Windows Forms App:
File -> New ->
Project -> Windows Forms Apps -> Ok
First, wee drag
NotifyIcon component from Toolbox to our form (it will appear below
it, as it’s not visible in the form area, but outside it)
And here is the first strange behaviour: if we run (F5 or Ctrl+F5,
but i’d suggest F5 as it allows it to kill the app if something
goes wrong, and it can in
this case) our app, the
NotifyIcon component doesn’t seem to work. The tray icon
doesn’t show up, and neither minimization nor clicking the „X”
button causes our app to minimize to tray.
That’s because our
tray icon is not set and we haven't implemented minimization by clicking "X". First the icon: in order to set it, we need the tray icon
itself :)
We can just use
Paint to create it – set the canvas size to 16x16 (this is the
standard tray icon size in Windows), draw something beautiful and
save it as .jpg file. Now rename it to something.ico – simply
change the extension! The ico files are simply graphics files with a
particular extension.
Now you can copy it
to project – you can just drag it to project name in Solution
Explorer view in VS.
It should show up below (myicon.ico) in the image above.
Now if you hit F5,
the icon should show in the tray :)
The problem is it
doesn’t do anything. The app still minimizes to the taskbar.
So let’s edit the
code. Double click on the form project appearing in VS. The form code
should appear, and it should be similar to this:
usingSystem;
usingSystem.Collections.Generic;
usingSystem.ComponentModel;
usingSystem.Data;
usingSystem.Drawing;
usingSystem.Linq;
usingSystem.Text;
usingSystem.Threading.Tasks;
usingSystem.Windows.Forms;
namespaceWindowsFormsApp2
{
publicpartialclassForm1 : Form
{
publicForm1()
{
InitializeComponent();
}
privatevoidForm1_Load(objectsender, EventArgse)
{
}
}
}
First of all, let’s make our icon actually do something: it should
show form if clicked twice, and hide it if clicked twice again. In
order to do it, select our NotifyIcon component in the designer
(Form1.cs [ Design] tab):
Now select the lightning icon in Properties windows (F4 if the window
is not visible), click the empty area on the right of
„MouseDoubleClick” and then double click on it again :)
Now when you run the app and double click on the tray icon, the
window should disappear. Double click on the icon again, and the
window should appear. Now close the window – let’s get back to
the code: we’ll add a context (right click) menu to the tray icon.
The remaining
problems are as follows: the application exits, when we click „X”
in the top bar. This is correct behaviour for most apps, but those
enabled on tray should keep working even if „X” is clicked (the
typical way of closing them is to right click on the tray icon and
choosing „Close” or something similar from the context menu). The
second problem is: the application still appears on the „normal”
taskbar, and we want it to be minimized only to tray.
To fix the first
issue, modify the Form1 constructor in this way:
publicForm1()
{
InitializeComponent();
this.FormClosing += this.Form1_FormClosing;
}
… and add the callback for FormClosing event below:
If you want to run the app now, do it using F5 (not Ctrl+F5) –
you’ll need to terminate it using „Stop Debugging” (red square
button or Shift+F5 in Visual Studio). If you forget about it, you’ll
have to close it via the task manager :)
Now let’s add a
possibility of closing the app via the context menu for the tray
icon. In order to do that, switch to the Form1.cs [Design] view and
drag ContextMenuStrip component to your designer view (window).
Now click on the "Type Here” area, type "Exit” and double
click on it. It should take you to the editor, with generated code
stub:
Of course, you can add more items to the menu (and add whatever code you want to it).
The last thing to do is to attach this menu to our tray icon. In
order to do that, choose notifyIcon1 from the area below the designer:
...and choose our ContextMenuStrip in the Properties window on the
right:
When you run the app now and right-click on the tray icon, "Exit”
option should appear (and should work).
To last thing to do
is to prevent the app from showing on the "normal” taskbar. To do
this, add one last line to Form1 constructor:
publicForm1()
{
InitializeComponent();
this.FormClosing += this.Form1_FormClosing;
ShowInTaskbar = false;
}
That's all for today - I think I was able to show you a simple stub of Windows app using tray in C#. If you have any questions about this - ask them in comments :)