 Joining at the floor is Jules. Thank you very much. Thanks, Majo, for those nice intro words. Today, I want to talk to you about Java, Seared Classes and Kotlin Seared Classes. And I promised this to be slightless, and what you see right now is not a slide, right? It's a Myro board. I work for Myro. We do boards. That's why I use, of course, Myro boards. And in case you want to follow up with that very small Myro board, please scan the QR code and then you can have those information. Mario gave a longer intro than I wanted to introduce myself. So just in case you want to follow up with more social media stuff I do, please follow the links. I do all of that in my spare time, as Mario correctly said, so I'm ahead of engineering the teams that I serve. We own backend representation of all my robots, which is a lot. Let's go into the topic real quick. I start first with Java Seared Classes and then Kotlin Seared Classes. I want to show you some code. I want to do some live coding with you. And at the end, I'm happy to get your questions. Java Seared Classes was actually the point that made me propose this talk because with the JDK 17, which is LTS, I came across that. I used Kotlin Seared Classes before. I was interested on how does it look in Java. And once I dive deep into that, I found out it existed as previously already with JDK 15. And the main point of Seared Classes in Java is that, by the way, also Seared Interfaces exist in Java to define their permitted subtypes. And it can look like this very simplistic example here. We would use a keyword Seared. We would define our class and with the keyword permits, we would define the subtypes for that Seared class. And in the definition of the subtypes, we would have to extend the parallel class and we would have to use keywords like final or others to make that sound for the compiler. And that setup, Java comes with that setup with some constraints that are important to keep in mind. So those subclasses, they must belong to the same module as the Seared class. And they must explicitly extend the Seared class with the extend keyword, for example, if you use a class. And you'll have to define modifiers. I showed you final before and Seared, non-Seared are also options. Now let's look at how Kotlin Seared classes look like. In my mind, those are super enums. So this is not an official definition or as official description, but still this is how I think of those. And the reason for that is that in Kotlin Seared classes, you'll define a lot of subclasses often as data classes. And those data classes often save state. And there are super because you are very, very free in how you define those subclasses. And I hope later I can also show that to you. More like an official way of describing Kotlin Seared classes is that those allow developers to fix type hierarchies and also have a handle on who is allowed to create new subclasses. All right, that was it for the introduction. Now let's look at some code. This is IntelliJ. This is Kotlin code. And this overall project does the following. It reads a GitHub organization and prints out the list of repositories. And I hope my code works right now. So let's check it out. The build is successful and this looks also good. So in this specific organization, I have two repositories and they are correctly read. So that's the organization in case you want to find it on GitHub. And I also share the link later with you. And now I have one function and that function verifies the GitHub organization. So I'm going to use a library. The library is the library is the GitHub API library for Java. It's initiated by KK. He was also the initiator of the Jenkins CI server and that library provides a GitHub object. And that GitHub object has a method. Yes, it has a method that get me the organization. And unfortunately, that method can throw an IO exception. And in this implementation, if an IO exception is thrown, it returns null. And in Kotlin and in many other languages, we don't like to return null. And now with CL classes, I try to explain to you how this code can be improved. Before we can actually improve the function itself, we need or I need to start a new CL class that holds those data that I want. And for that, it's impossible to increase the font size a bit. Yes, let me do that. Oh, wait, I thought it was possible. Maybe in view or something up there. Maybe there is. So let's assume I'm going to do, I'm going to use this. Would that help? Yes, perfect. Looks very good. Thank you. Okay, good. I now need to switch from time to time back and forth. Because I need to, I need to create some classes, but whenever possible, I go with the presentation. So first I need to create a sealed class. And I'm going to call, I'm going to use the, I'm going to call this class GitHub organization. And now I have the sealed class. And now I need something in there. And for that, I'm lazy, right. As any other developer, I'm also lazy. So I'm going to use another seed class that I wrote before. And I use that as a inspiration source. And now I enter the, okay, very good. That works. So I use the same mechanics as in this sealed class. I want to be able to react on the success state. So the GitHub organization exists, or the failure case, the GitHub organization does not exist. For example, because there was a string provided that references an organization that doesn't exist. So in the success case, I'm going to define a data class. And in that data class, I want to hold the handle to the actual GitHub organization from the library. And that is a GH org for me. And now the idea is smart enough to, to give me a hint what type that could be. So that's the type that I'm going to use. And seed classes in Kotlin, and they request you to refer to the implicit constructor. And this is how I do this. And now I have a first data class for my seed class, which is for the success case. And now I'm going to do the same. Or the failure case. And in the failure case, and there will be some error message. So something will tell me whatever went wrong, at least I hope so. So I'm going to define an arrow. And that's just a string because that's the error message and as before, I'm going to use the implicit constructor to make the compiler happy. Now I have this seed class with two data classes. And now you may spot already the, the super notion of the super enums. So this type is completely different than that type right. And in Kotlin, you can, you can do anything you want. And you can give it any, any type you want it for those, for those data classes and that's something that really makes it kind of super to me. And that's why I like so much the, the super part in, in super events. So he's not happy with, with that, but we don't need this data class anyway. So let's look on, on how we can use this. So I need to exit the presentation mode for a minute. I need to go back to my original code. So here we have now the function and I want to use this data class. So I'm going to wait where is my class is my class. I'm going to put this on the side so we can see this. And now again, go into the presentation mode. And here's my function that, that I want to change in the success case. What I want is, I want a data class to be invoked. So once I do this, I need as a pattern in this PH org that is of type, GH organization and access instance is provided to me with the get organization call. Now I have usage of my data class and now the compiler is not because the return value is different from what I defined above. So see here, I defined here that the return value is of type GH organization that can be null or it can be an instance. And now the return value is different. Now I use my data class as a return value. And then the compiler is happy for the success case, but unhappy for the failure case. And luckily, I prepared the failure case. And now I can do something similar than in the success case. And I can use my failure data class in order to hold to have a container for this. And I'm going to use a localized message for the, for the failure case in case an exception. And now from my perspective, the, the code of the function looks way better because there is no null returned anymore. And failure and success and many other cases could can be handled with the data class that I, that I called GitHub organization. You may notice that the footprint now changed the return value is different. So here we go on how this function is called and how, what we can do about this. So here we go. And here the compiler gives me yet another arrow. So the earlier the code was in a way that GitHub organization in line 43 can be null. And it will affect that it's not a used to let a statement to make sure only if it's not now and the list of repositories is generated and then print it out. Now this method, sorry, this value is of different type. So I need to be a differently with the situation. So Kotlin has a nice way of dealing with those data classes which is pattern matching. And what is used here is the when a statement so when that value has a certain type, we can ask for the type. And we start with the GitHub organization success case. And in case there is a success will do something. Let's let's do this something. I'm going to reuse some of the code I have down here. And now I need to provide the the right value, because the compiler is not happy with that it because this it doesn't exist anymore. And here the right value is the horg and that I defined in the data class. So let me show you this one more time. See here this is the gh org that is of type gh organization like the library provides. And that is exactly what the list org repo and expects. And now we are almost ready to go but I forgot one thing which is whenever you you use pattern matching and this whenever you use pattern matching and with when it needs to be exhausted and you know also see the the hint that the IDE provides. And there are two options one option is that you that you say else. I encourage you not to do that, because this is a catch all and in case you define additional data classes on your C class, then you may forget to handle those cases differently. So I'm going to be explicit and I say in case it's a failure. And I do something else. And in this case I just say print me the error message that is describing the failure on the command line. Again, I believe the code is much improved. Instead of handling nice with the lab statement. We are very explicit because we haven't we have a value which refers to a seed class that seed class can be pattern matched, and you have those cases that you have a class where you pattern match on and where you decide what is the actual logic logic that you want to do this is logic number one, and this is logic number two. So hopefully that whole code works for that I need to exit the presentation mode and start the terminal one more time and start the code one more time. Hopefully that works to build a successful which looks good and also the repositories are as expected. Now, let's see how that looks in Java. By the way, Mario, how much more time do I have is it that you have around seven minutes more time. I won't I won't be able to finish that in seven minutes, at least not what I, what I planned to do. Anyway, let me try to give you a hint on how it works with Java. So in Java, and I prepared a similar situation in this method, it was a tourist and again, there is an IO exception that can be thrown and if that happens, it returns now and that's not the way I expect the code to be. That's why I want to change that. And I do change that with a new package. And I call it. So the package is only there for the college repository and the package is only there because I want the code a little bit to be all that. And here. So I actually I wanted to show you see it classes in Java but now I'm going to shortcut and I start with a sealed interfaces in the code on GitHub you also find the examples for sealed classes. So that's an interface. And what I want here is a good repository. And again, I'm lazy. I'm going to use another code that I wrote before. And here, let me enter the presentation mode one more time. So I'm going to use the sealed keyword for the interface. And then I'm going to define the sub classes. In this case, those are not sub classes. In this case, those are records. And to define what is allowed and it's one success case. I'm pretty sure you know what is the next, which is. But now I need to define those classes and for that I need to exit the presentation mode. I'm sorry for this jumping back and forth. And I'm going to do again yet another cheating. So I need a new Java class, which is a record. And it's a success. Oops. Sorry, this was wrong. This was wrong. Yeah, it needs to go here. And another record, which is fade. And now I need to define what is the parent class and I use the implement keyword for that. And that's the parent class. And I do that for the success case too. And similar to the, to the Kotlin case. I define an arrow string that holds the arrow for me. And I define a GH organization object that contains the GH organization. That looks promising. And now I need to go back to my method to change the code. So let me enter the presentation mode one more time. I'm going to return a new GitHub repository. Access in case list repositories returns me the list that I want. And now the, what's wrong about this one? It's a list. It's a list. Let me fix that later. And also what would have been an issue in case I wouldn't change this. So I'm going to change the return value. It's, it's my data class. In this specific case, my sealed interface. And also for the case, I'm going to return similar to the Kotlin example. So I'm going to return a record, which gets me the localized message in the arrow. Now, the list repositories returns. But GitHub repository is has does not has a list, but only one organization. And that must be a list of each organizations. It needs to be imported. I come on. New import that please. Yes, import class. Okay, good. That looks good. And now this needs to be imported as well. Okay. And now it still has this. It was wrong with the definition that I did here. Yes, I was wrong. So that must be the age repository. That needs to have a CD color. Okay. But now the function works at least from a compile perspective and there is still one problem because the return value is different. Mario, do we have three more minutes? I think we can extend like a couple of minutes. Sure. Thank you. And now I need to react on the, on the success and on the failure case. And what is so far expected is a GH repository item from the actual library. But what I provide is my own sealed interface. There are the specific records that implement that interface. So. In Java, and you would do. And take those cases with. With an if statement. And you would ask. Is repose which instance of is that guy. And the instance would be get up organization repository success. And if it's a success, then let's do something about this. And in case it's not a success. And the instance is different. And in this case, then handle the failure. Oops. Sorry. Now I need to go back. I clicked on the wrong thing. Sorry for that. So this is where I wanted to click. So I need to go through the failure case. And now let's double check what is the arrow here. Ah, the type is wrong. And now something. It doesn't make. Okay. So in the in the success case. I can. I can use the object retrieve. Right. Wait, this is this is strange. And so this was this was wrongly named. I'm sorry for this. This is really confusing now. And nevertheless, what. What happens here is that I can iterate over this. And I can execute it for, for each that I wanted. That should have been called a repository and not this. This was my bet. And in the, in the failure case. It up organization failure. There is this error message. And similar to the, to the Kotlin case, and that out. In case an error happens. And last but not least, I want to, to tell you one thing about this Java case, what is really nice about this instance operator is you don't really only check for the type in this specific case for the record type. You can also give it a label. And that label is a handle to the instance. So I can use that instance and I can call methods or methods that are fine for that. And to wrap it up. If you, if you want to compare Java and Kotlin, and you come across sealed classes from my perspective, there is no major difference with JDK 17 Java really caught up, especially this sealed interfaces slash records approach that Java now offers and is from my perspective on par with the Kotlin approach. Personally, I still like the Kotlin approach a little bit better because the sealed class plus the data classes, they all fit nice into one file, whereas in Java, you will have interfaces and records at least in my version in different files. But that's such a small difference that you can't really say one approach is better than the other. And in case you need to decide Kotlin or Java for, for a given project, other things like how, how good are the developers that you work with in one or the other language are way more important. The sealed class approach is at least from a conceptual point of view, almost the same. And I hope that code helps you to, to remember that. And in case you can't remember these scan one more time, the QR code, you will find down there the GitHub repository with the code, also with the sealed classes in Java that I couldn't live code with you. And now I'm going to take questions if there, if there is questions.