Transcription
Okay, here is the translation of the provided Georgian text into English, following your rules.
So, today's lesson is the fourth, and today we will go over interfaces, which in our language is the same as abstract classes. That is, a class-like type, similar to an abstract class, where only abstract methods are described. However, interfaces were slightly modified in version 8. So, before version 8, the interface as it was in Java, is the same in C# and other simple languages. For example, in some languages, this is called a trait and not an interface, but here we call it an interface. And we will go over enums, which are also in C++, which simply allow us to describe a list of something, a set of a desired quantity, of something. It can be infinite, well, it's a set of something, just like a desired set. And then we will discuss some things in the main function because we have really forgotten about this main function. So, there is a lot written here. This is a bad slide, a synthetic slide, so to speak. And I will simply tell you what these interfaces are. An interface is like this person. So, in Java, everything is class-like. So, an interface is actually some kind of abstract type, class-like, to which you can write "abstract", but it's not necessary because it is already abstract. You can write "public abstract interface", but they just don't usually write it. And the methods described inside are implicitly abstract, meaning they are like abstract classes. So, we covered abstract classes before, and an interface is like an abstract class, just with some nuances. And from version 8 onwards, they added this "default" keyword for these methods, which can have a body. Well, we call this implementation. Let's first discuss what a classic interface is, and then what was added after version 8 and what these additions caused. Now, let's create a project. You can also create one. This is a very fast computer. Create a project in May and let's call it, I usually call it this. Version 22 is written here. It's enough for us. Don't forget to specify the group correctly here. You can change it later, it's okay. And as always, you start by setting the table, right? Before you put food on it, you have to set the table, so to speak. And setting the table means creating the root package in "source main java". Oh, we don't need this. In "source main java", first create the root package. The root package is "geusngu". And then you can name the project, say "lesson". Well, you can't use a hyphen here. You can use an underscore. And for, well, they don't usually write it like that. You can just leave this as the root package name. I'll change the version a bit too. Let it be one zero zero. What is written here, "snapshot", indicates that it is some kind of test version. Turn off this POM file, don't delete it. This XML file is just the POM file opened. And here I will first create the main class with the main method. I'll call it "launchers" or "app", whatever you want, or "interface demo". The class name will be this. I'll make it "main", and if you want a minimized main, you can do that too, as you wish. It's just that in this version, this minimized main feature is not available, so to speak. Now, let's create an interface. But what is the idea of an interface? Hello people, thank you. >> Hello. >> So, an interface is an abstract class, but with abstract methods only. In my language, this means the following: that the word "interface" seems a bit incorrectly conceived, but maybe it's correct, I don't know. In some languages, they give it a different name. So, this is a purely abstract type, meaning an interface is like a contract. So, what is a contract? Something is written that must be fulfilled. Something is written on paper, and it must be fulfilled. And an interface is also a list of properties that the classes implementing this interface must fulfill. So, like the idea of an abstract class, right? It has virtual methods, and its children must definitely override these virtual methods, meaning, in our language, implement them. And let's first describe such an interface. What could this interface be? This contract, for example, "Human". You can describe things with abstract names in the same way. Well, you can also give interfaces different names. I'm just using it as an example here. I chose "class" by mistake. You can choose here >> Interface. I choose >> Yes, an interface. And we will go over the other types. This "record" is simply a class that is immutable, something like that. This is nothing. This class-like type is something. And we will go over enums today, and then annotations later. We can also look at records. Some call it "enum" because they realized it's an interface. The terminology in C# is to name the interface. And what can an interface do? Well, you can directly write inside it, for example, "void eatFood". You can also say "String sayHello(String name)". Say hello to, and so on. Let these two methods be enough. And see what I told you. So, this is abstract. It just highlights it in IntelliJ. Highlighting means that no one is using it, or it's better not to write that keyword unnecessarily. And in the case of an interface, you can simply not write it. And here, where it says "void", now you might think it's default access. No, in an interface, abstract methods are written directly like this. You can omit these keywords, but I'll still write them for clarity. Is it clear? So, by default, an interface is abstract, of course, and its methods can be written directly without a body. And it is understood that these are abstract. I don't know, let's do it this way. Let's put it in comments. And here too, it's something like an abstract class, right? It's just called an interface keyword. And now, when we introduce a class, for example, "Person", what happens? When we introduce "Person", how do we write that this "Person" is a child of this "Human"? And we have to use the "implements" keyword, not for interfaces. We have another keyword, "implements". "Implementation" means realization, meaning for a method. And for an interface, it means it's the same as "extends" for interfaces. So, the abstract methods from this interface will come to me, and I have to override them. And if you are lazy, you can click this and then choose what to override, or directly ask IntelliJ with Alt+Enter to implement both of these methods. And this is implementation, meaning overriding. So, writing the body, writing the implementation for the methods. Let's say this is "eatingFood". Oops, "eating". And here too, greetings and a name. Well, here you can call this "String.format" like "printF", or you can write "String.format". This is also like "printF". So, there are different options. These were added later, formatters. So, it's like "printF" but for strings. And this builds a string where this name will be inserted in this place. This is more like a string formatting method, like using a plus sign. It will fall into the full string. Right? And if you do it this way, it won't fall. However, write it as you see fit. Optimization is not our goal yet. And the usage is similar to an abstract class. Just remember, you can implement more than one interface. So, you can write a comma here, and "Human" can be a "Being" interface, so to speak, a descendant. Well, this can also have something. Since it is a being, it can have a "void die" method, or something. And then you also have to override this method. >> [Music] >> Yes, something like that. So, it turns out that this "Person" fulfills two contracts, so to speak, the human's and the being's. Right? Now you will ask, "Wait, Vakho, didn't we say before that we have single inheritance for classes?" Why? To avoid problems. So, here, if the parent has a method with the same name, and here too, in this case, we will have the diamond problem if the descriptions of abstract methods with the same name are repeated. This diamond problem no longer exists because the contract says you must implement this method, and the second contract also says you must implement this method. And you override it once, and you fulfill both contracts, both requirements. So, there is no problem in this case. Hello. >> And during usage, wait, what were we saying? So, usage is similar. You can use interfaces in polymorphism. For example, write "Human". So, write a method, for example, "public static void feedAllHumans". And here, write a method that works on humans, "feedAllHumans", which feeds each human. >> For loop. Hello. And on "Human", we will call the method that we see through the eyes of "Human", for example, "food". And then you can introduce "humans" here. "Humans". Well, I don't know if we have this AI assistant here. Well, you need to log in, but you can see in the recordings that I sometimes use this AI assistant for tedious tasks like this, in the control panel. And you tell it, for example, to insert some "Person" objects here. "Person" objects. This "Person" is probably very simple, not anything special. Let's introduce "private String name", "private int age", and introduce a constructor. And I told you that you can still override "equals" and "hashCode", but how many times will you change this "equals" and "hashCode" and if you change the string, you have to change it. And see these methods. No, not these, one second. These methods are a bit serious, more so than "String" and things like that. >> And what did we say? That it's better to write good methods after the constructor. And with scrolling, you can use Ctrl+Shift to move these methods up. And let's shrink them and only show the methods that are important. And let's also include the getters. Let's shrink both getters again. And well, let's leave these methods. So, only leave open, so to speak, not collapsed, the methods that are important. And I write between these, between "Person" and the rest of the useless methods, this "hashCode". Let's move this "hashCode" and "toString". And now, let's create "Persons" here. Let's say "John Brown", still 35. Let's end with commas because other people might come. Well, AI gave me 61 here in the previous recording. So, "Tom Cruise". It's written like this. And let's say "Meryl Streep" is 55. From actresses, I don't know many names. And let's say it's just a man. And men. So, I can call "feedAll" like this. So, when I look at it, you might say, is this an interface, an abstract class, or a parent class? You can't tell from here, right? Because in terms of usage, you use it similarly, as a reference of the parent type, right? Polymorphism. So, it's "Human", and then any of its descendants can be created here. And here too, in terms of usage, I use "Human". And to understand if it's an interface or not, look here. This green color in IntelliJ shows it. Or you can go in and see that it's an interface. Let's delete this because we need to get used to these rules, so to speak. This is the idea of an interface: that classes can implement one or many interfaces, and interfaces describe the contract, meaning what properties the implementing class must satisfy and implement. How is it written in Java? Where it gives you errors. >> Where did it give you errors? >> It's that when I tried to implement the "Human" interface, it gave me errors. Ah, okay. Try to fix it, and then I'll come and look at it because I don't want to make a recording or pause during the lecture. So, what's the advantage of using interfaces? Let's look at this example. Here, we use an interface in this method. So, the point is that you can implement more than one interface, but a class can only have one parent. If someone has a parent, for example, if I write here, I don't know, "Employee". Let "Employee" be a child of "Person". Well, since it's a child of "Person", what does it ask for in the case of "Person"? Well, now it tells me that "Person" doesn't have a no-argument constructor. And when I automatically wrote this no-argument constructor here, and then "super" no-argument, remember when I mentioned this? We have a compilation error because this one doesn't have a no-argument constructor. You must write the parameterized one manually. Okay, my compiler, but let's add "modified" here so that the child can also use it. Let's write a constructor. And it gave me such a constructor. But let's add "protected value", say "int annualSalary". And it gave me a constructor like this, where it passes the parameterized name and age to the parent and directly assigns the last parameter, the salary, to its own field. The rest of the methods followed, but what methods didn't follow in this case? And it's better to override "equals" and "hashCode" again. Meaning, the comparison logic with another object like me. And the second is the logic for generating a unique integer using parameters. And "toString", which is simply for string conversion. And you can outline all three here. And it will give us a string like this. And what are we saying? So, in this case, you cannot use the polymorphism of an abstract class because, for example, if I have "Being" abstractly here, and it says "Person", and I can't change it. So, what should I do now? Here, it should also extend "Person", and something like "abstract class" won't work. And an interface helps us in this case. And remember, you first write "extends" and then "implements". You can't write it the other way around. And you can write "implements". Well, I don't know, this will be redundant because "Person" implements these. And it is understood that the children of "Person" will also implement them automatically. And writing it here is redundant. It's the opposite. If you write "extends" first and then "implements", and one or many. Here too, you can write something like "Human". Well, I'm just writing it as an example. So, the point of an interface is that you can have a hierarchy where someone is a child of someone, someone is a child of someone. Suddenly you say that this is an implementer of this interface, this interface. And then you can use this person here without any problems, and no hierarchical structure of children and parents, ancestors and descendants will be broken. So, it's good, these interfaces. That's why this is the classic understanding of interfaces. Now came this version 8. In version 8, they introduced lambda expressions and the API, which we will cover. We will cover lambdas. And they wanted to introduce some methods in the collection classes, which we will also cover: List, Set, Map, Stack, and so on. But these collection classes were made with interfaces. We will see that. And if it's made with interfaces, you cannot introduce something without having to make an implementation in the implementing class. Look, if I introduce something in this "Human", it will force me to override all the methods for every "Human" that implements it. And "Person". Well, "Person" is a child of "Person" anyway. So, in "Person", I will be forced to implement this method, just like I implemented these methods here. Right? And this breaks, so to speak, one of Java's features, which is called backward compatibility. The idea of compatibility is that on a new JDK, or a new JRE, so to speak, new JVM, old compiled code should also run. And if I go and add methods to new classes, well, it means that the old code, the old compiled code, thinks that this new class doesn't have such methods. And suddenly it does. So, it's not in sync. You cannot run old compiled code in an environment where you have changed things in classes and interfaces. And that's why they decided that since people are generally lazy, they came up with the simplest solution. Someone said, "Wait, let's allow interfaces to describe method bodies." That is, non-abstract methods. And in this case, we can, for example, where it says "eatFood", write the word "default". So, they thought, let's use the "default" keyword, which is already reserved, so we don't add a new one, because that would also break backward compatibility. And "default" is used in switch cases, default. And let's use the "default" keyword. And if you write "default", you will have to write the body in this interface. And for example, in the body, you can write something like "human eating food". And if you write "default", it is understood that this is default access. So, the body of interface methods. And the rest, now this logic will be repeated. It will work. Of course, we don't need to correct anything. "eatingFood". But look, with this "default", I can now add a method in the interface that won't tell the implementer, "Oh, override this because it's a body method." So, it's similar to an abstract class, in a way. In an abstract class, we can have abstract methods and non-abstract ones. Okay. But then they suddenly said, "Wait, now writing some methods, because of this, we have to do the same thing in this interface, or make it a bit more flexible." With the addition of "default", they said, "Let's also introduce the ability to write default methods." So, they said, "Let's also have the ability to write static methods." Let's say "secretly eating food". And well, you don't write "default" for this. That's an error. You directly write "static". So, if you write a "static" method, it's understood that it's of static type. You don't write "default". And then you write something like "secretly eating". So, this is already an example of eating food secretly. This method will not be inherited by the children. More precisely, it will be inherited, but it won't be accessible. So, it's like a static method, like in abstract or regular classes. And then suddenly someone said, "Wait, what is it called here?" So, we also forgot that in interfaces, you can also describe static constant fields. So, in the classic sense, you could describe two things in an interface: a static constant field and abstract methods. So, a static constant, for example, "public static final". This is a constant. You can describe it, for example, "String FIRST_HUMAN_NAME". We usually name it with capital letters. It's not mandatory to name it with capital letters and underscores, but we do it so that when you use it, you realize, "Oh, it's likely static and a constant." And you don't have to write "public final". You can write it like this. So, initially, there were only these two things. And then they said, "Wait, maybe I want to use this and use this constant in a method here, or something." And finally, they said, "Okay, let's introduce the ability to describe static methods in an interface." And they introduced static methods. Well, let's call it "doSomething" or something like that. And we can already do this. By default, people, by default, if you write things without a modifier in an interface, it's likely static. This is also static. And then suddenly someone said, "Wait, let's add a "private" option to this." And they also did this. And this led to the addition of this new functionality, the necessity, and the preservation of backward compatibility, which caused this mess in interfaces. You might not even remember it because default methods, static... Just remember that an interface allows us to describe static constants, as well as abstract methods. The rest, these "static" methods, "private static" methods, are already for very rare cases. They added these options: this option, this option, this option, and this option. The rest, these are already in classic interfaces in other languages. This, well, this is basically understood, but maybe in some places you could also describe static fields in an interface. I don't remember in C#. Probably only abstract methods are described. Okay, now see, with these additions, you will ask, "Wait, Vakho, are we returning to the C++ problem?" The problem was multiple inheritance. And if methods with the same name, say "hello", come from class A and class B, and are implemented, which "hello" can I override or use in the child? How do I specify that? And this problem also arose. So, if you describe, for example, "eatFood" here, and also describe "being eatFood" here. So, see, this "eatFood" is the same. But let's say we describe it like this: "being eating food". And then suddenly you might introduce something, I don't know, "Eva", which says, "I am Human and I am Being." And in this case, there is another nuance. Suddenly, interfaces can have a hierarchy like classes. So, one interface can "extend" another interface. And the logic is the same, people. The logic of "extends" is that I inherit everything my parent has. Here too, if one interface extends another, what does that other one have? Well, mainly abstract methods. And I will inherit those abstract methods. That's all. So, you can write "Human is like Being", meaning extending the interface. Well, logically, it makes sense. You can think of something like that. Because a human is also a being. Then you can introduce an "Animal" interface, and that can also extend "Being". But let's consider this example. In this case, my compiler tells me, "Vakho, this class A must either be declared abstract or implement the abstract method." Okay, let's implement "sayHello". But see, besides implementing "sayHello" and "die", I have some error. And what is this error? It says, "Unrelated default for eatFood from types." How can this be resolved? So, I inherited the same named body method from one, and the same named body method from the other. And this is Java, not C++. This problem must be solved. And Java tells me, "Vakho, solve it." And the solution is, well, there are three or two ways. One is that my implementation, meaning it's mandatory to override it, there's no other way. And one option is to write my own implementation. So, it has its own parent. The other has its own. And I write my own. The problem is solved. This is one option. But instead of my own option, I might say, "I'll use the Human's option." And as a prefix, like we write in C++ when there's a problem, to specify that I want to use the method from this Human, or the method from Being, with the same name. And as a prefix, before using the "super" keyword, you write whose "super" method you want to use, for example, Being's or both. So, this is one option. Or, well, you can think of combinations. Let's leave it like this with "Human". This is the only way to solve the diamond problem: you must override it, and then use whatever you want inside. Using constants. Now, here you can also write, for example, "FIRST_HUMAN_NAME". No, let's just return something like "String.format(FIRST_HUMAN_NAME)". Let's do it with a plus sign. I don't care about memory. It's a string. And why isn't there a prefix for "FIRST_HUMAN"? Because it's described inside "Human", and it's already understood that we mean this static field described in "Human". It's not necessary to write prefixes. It's not necessary to write "Human.Human". Where a person understands, don't write prefixes when using static code. This is interfaces. That's it. So, we saw Java 8 interfaces and post-Java 8 interfaces. If we write code with interfaces, meaning parts of the reference are interfaces, say for class properties, return types, local variables. But if it doesn't work out that way, then replace it with abstract. But if it doesn't work out with abstract, well, replace it with some class. Now let me see how much I've talked. And let's see if anything else can be remembered about interfaces. There are no simple examples here. Examples of default and static methods. Is there a discussion about the diamond problem here? If you don't tell these AI assistants, they won't write anything for you. And this is part of enums. And besides enums, we also have some practical theoretical parts related to the main function. Now, let's pause. It was a whole topic. Let's take a break and then continue with enums. And I'll tell you in advance about enums, because I always repeat that. There is a primitive type, and there are class-like types. There are no other types. If you consider "type", meaning value, you can use primitives and object types. There are no others. That's why an array is an object. A class, well, you create an object from a class anyway. An interface is a class-like type. An abstract class is also a class. And an enum is also a class-like type. An enum is a uniquely introduced type that the compiler treats... It's not like that in Java. Everything is an object type, except for primitives. So, the second topic is that students smoke. So, which programmer doesn't smoke cigarettes? Remember that. So, the second topic is this. Another topic is enums. And who is an enum? Why is it called an enum? What does it mean? Enumeration means enumeration. Something numbered. Something numbered means listed. And in Georgian, it's called some kind of countable type, something like that. They translated it like that in C++. In the Georgian version at TSEU, for example. And what does this list type help us do? What does it do? For example, a C++ type example. An enum is approximately like this. And in Java, you can write it with this syntax. And you can, in short, describe an enum like this. And give it a name. We also name enums like class names. And these constants are usually named with capital letters. These constants are a desired number of enumerations. This enum is intended for programmers. No one cares if the user uses an enum or integers or strings. For example, to list the days of the week, it's simply more convenient for the programmer. If someone says, "Do something, describe the type," and if that type implies a desired number of constants, for example, gender. Right? Right. So, for example, days of the week, names of months of the year. Or, for example, a limited number. Like fruits. Well, they might add something to fruits later, but it's a limited number. Like planets in our system, and so on. In such cases, you might say, "It's better to describe an enum and use it." And it will simplify your code writing, the code will be readable, and it will be more concise, flexible, and there are many things in enums that are not in C++ and C#. And in terms of usage, it's very simple, just like a static constant. It's used like this. But inside the enum, it's described. Look, like this. You can assign it. Look, like static constants. Because in reality, this entry in the enum translates into static fields of a class. And don't get confused by the usage. So, the value can only be assigned from here. "Status.upload". Right? Status.result, for example, "failed", "indeterminate". You can also introduce an enum for such a desired number of constants. And now you will say, "Wait, Vakho, what is this? What methods are we calling? What's going on?" There are no methods written in the enum. What are these methods? Is an enum a class? Yes, an enum is a class-like type, but limited. So, an enum cannot "extend" another class type. All enums "extend" something. So, you can't write "extends", but it's understood that an enum "extends" some kind of enum class, and from that class... But you can't write "extends". You can write "implements" an interface and override the abstract method of that interface. You can do that. And also, these methods, look, these... Well, not these, but all enums are descendants of some enum class, and from that enum class, methods come to me. Because a class can have fields, constructors, methods. And the methods are what come to me from that enum. Now, our task is to practically see what methods are inherited by all enums from the parent enum. Where is this parent enum? This is our parent enum, which you cannot "extend", of course, and which is the parent type of all enums. And look, it has these. If you are directly interested, if you open a class or interface in IntelliJ and have the cursor placed like this inside, and you are interested in what methods, fields, and constructors you have inside, you can click here, and "Structure" will show you what methods you have, what constructors, and what fields. So, at the end, it usually writes fields. And we have fields: "name", "ordinal". Well, "name" is understandable, right? "name" is the name of the constant. If it's written "MAIL" in capital letters, it will be in string form. But what is "ordinal"? "Ordinal" is simply the index. If it's the first constant, it's zero. If it's the second, it's one, and so on. "Ordinal" is "final". You cannot change "ordinal". This "ordinal" is the same as the integer assigned to an enum in C++. They call that "ordinal number". And they brought it here too. What other methods do we have? We have the "name" method. Okay. The "ordinal" method. Okay. These are getter methods. If "toString" is overridden, which returns the "name". That's why it returned the capital letter "MAIL". Because if "toString" was overridden. And there are other interesting methods. Look, we also have "compareTo", and some trivial methods. Like "valueOf". Well, "valueOf" is also a bit... Let's find a more interesting method. Okay, well, in short, we have a method like this. It wasn't visible there. In that list, enum, not enum, but our "Gender". So, "Gender.valueOf("MAIL")". It simply takes the string "MAIL" and returns the constant "MAIL". If it doesn't find it, you will get an exception. We haven't covered exceptions yet, and we can discuss them in the next lesson. But we don't need "valueOf". Let's print all "Gender" values. What does this return? What does this return? How can we find out? Here on the right, it says what it returns. "Gender" array. And you can directly iterate. Or first, return "genders". And then "for gender in genders". It's a bit of a silly enum. You can think of interesting ones. For example, countries. Languages. Well, I don't know. Races. Not races. Look, "ordinal", "name", and our "getHumanReadable". And we can also override "toString". For example, if the senior said, "Vakho, let's just override toString and return this 'human readable name'." Okay. And when we print this directly, the human-readable names will be printed. So, strings. And when I run this "Interface Demo", look, what beautiful names it wrote there. Capital "MAIL" and capital "FEMALE". It's no longer written. Oh, what's going on? Yes, this is an enum. It just depends on how you use it. And many have, for example, related to countries. There is a library where an enum is described, where the author listed... Well, I don't know how many countries, maybe 100 something. So, it listed all those countries. And for these countries, there is a standard language designation, something like Alpha-2 or something called 200-digit symbols. For example, Georgian is "ka", English is "en", and there is also a country code, a 300-digit symbol. For example, "rus" for Russia, and so on. So, they also wrote these as fields for those countries. It's a very good library. And it's not just one. There are many such libraries. Java doesn't come with such things, but some people have made them. And you can search for them. For example, you can go to a repository. For example, these ISO standards. So, now you will ask, "Wait, Vakho, did someone sit down, many people sat at one table, and said, let the language code for Russia be the 200-digit symbol 'ru', and let 'rus' be the country code for Russia. And in Georgia, 'ge'. And 'ka'? Why 'ka'? Because it's Georgian. And maybe 'et' for Ethiopia. Something else couldn't have come out. So, did someone agree on that? Yes, they agreed, and they created the ISO standard. I just don't remember the code. ISO language names. Yes, this is it. List of ISO 639 language codes. And there are also country codes. And if you look, here is Abkhazia. What is this? Why did it give me this? Okay, Armenia. Okay. "h". I don't know what it means. "Arm" is not there. And that's it. This is just a theory. Apparently, there are other sets. I don't know. This is also... You have to look into this. Here, approximately, it's understandable. This is a 200-digit one. This is a three-digit one. Let's look at Georgian. "ka". Is Georgian not there? Let's look at "ja". Okay. And there's also "cat". I don't know what "cat" is. But usually, they use this. So, when you do localization, and you specify the country, and you can see this in Maven, for example, "Maven country name library", something like that. This country code includes... And it's "ami". Okay. We can trust this AI and use it. But don't always trust it because it hallucinates. Okay, let's take this, for example, "h". And the last version doesn't have compile dependencies. So, it directly uses the classes and libraries. And how did we do this? Adding dependencies in POM. [Music] We introduced a tag called "dependencies" (plural), and inside it, you write this "dependency". And "depend" is red because here "refresh".
The Roman Empire should download this locally. It will download to the local repository, put it in, and then attach it to my project. Here, it's attached. And when it's attached, then I don't know which of its classes I should use. I can use it here. For example, if you have a country code, what language does a person speak, where are they from? Let's add a person. We've eaten this person, but it's okay. Country code, look here, country, country code, country c. Well, how is the origin, ethnicity, origin, or origin? Or I don't know, let it be called "Kunythiqdi" or we'll understand what it is. And these other things, this constructor needs to be regenerated from scratch. These also need to be regenerated from scratch. Let's quickly generate the getters too. Well, I usually delete them all so that it gives me everything from scratch, humanely. That's why I'm doing this, otherwise you can also change it yourself if it changes, of course. Impl, implo. And why did it change? One second. Yes, here in the constructor, it will be needed to add the country code, and then pass the country code here. And these will also change. So, this is very much, I'm talking at the same time, that's why these things are written quickly. I deleted this in vain. In short, equals, hqdi, and to string, for string, everything should fit, and then here in the interface, origin should also be added. USA, yes, country code US, like this. And then this country code US can also have something. US is also a type because it's a name. Look, this US is also a name, or rather, in USID, there is a record of this type, of course. It's just US, if here again something, like get alpha 2, get alpha 3. Let's print it first, let's see what it prints if it's a string, what it does. And if we don't like it, I don't like it. I think these are constant names in capital letters. Let's print it during printing, person's string, not hqdi, but alpha 3 should be printed. Well, I don't know, the boss said, let's imagine, and USA, USA, this is better. Yes, so look, my person has become more elegant with the help of another library's enum or my enum, so to speak, more informative. For example, when you describe a car class, for example, when you describe a car class, yes, you write, like, new car, new. It could be an interface, yes, and health. And maybe in this car, you describe, for example, model, meaning the model name of the car. And maybe someone will say, yes, yes, won't it break, protected in, or in? No, let's double to speed. But someone might be a schemer and say, is this miles per hour or kilometers per hour? And to differentiate this, your brain should work like this now, when you have time, there are two options, enum. I can introduce it, and you can introduce an additional enum. Let's call it that. What should we call it? Unit of measurement, measurement, yes, unit. You can call it unit, and this unit can be something like speed unit, let's say speed unit. And you can create this speed unit. Let's call it this and create an enum. Look, this helps me. It shows me in red, I don't know who this is, what should I do? And there are different options. So, do you want to create a class for this? Somewhere here, I tell him, let's create it, my friend. Let's create it in the route package itself, and let's write speed unit, miles, kilometers, per hour. Yes, and now, with the indication of this speed unit, we know what the speed is. Or if you are more motivated, you can, since these two records are related to each other, yes, we know the principle of abstraction in Java, the fourth one introduced. You can take this out into a class. So, instead of this, you can create a class named speed stop speed. And this class will contain this field, get, getter. Remind me, I'll definitely say a word about records, don't forget. Yes, like this. So, look, I introduced in the car what type of speed it will be, what unit it will be, and what that speed will be. And since both of them were related to each other, I took them out into a separate class. And I can already, well, you can call this stop speed altogether, to speed, because it contains speed. Yes, here, you can call this stop speed, let's call it speed. This will also change the names of the getters. Refactoring. And I think it changed here too. No, it didn't change here. And unit. Here too, you can change the name of this, call it unit. I don't think it's a problem, it's the same. Yes, and we use to speed here. And look how beautiful our car class has become, its getters. Now you will say something like this: Vaho, all these getters, equals operations, this is not necessary. And if it is necessary, my class grows in size, the code grows. So, this code of mine is an important part of this class, what they call fields. Yes, this field is an important part, and the rest are banal methods, getters, setters, constructors, some unfortunate things. And is it possible to avoid writing this? Do we have a way to write it automatically? Yes, of course, we have a way. For this, they introduced record classes from the 11th version, or from the 9th, I don't remember exactly. Record classes, record type classes. And a record class is simply a class that has constant fields and for which getters, the implementation of the primary constructor, and also hashcode and toString will be automatically written. So, a record class is good if you describe a constant class. This car resembles a constant because these do not change. Like, top speed resembles a constant because you might not want to change the top speed. And well, constant, meaning it changes. Yes, well, in short, that's why it's called a record. What is a record? It's a record, it's a record. Let's use this, people. And what did I tell you? If you want to use it quickly, you can write it here, in the main, somewhere. And let's create a car here. Let it be BMW, I don't know, what is this, asdf version, and top speed will be new top speed, and the speed will be 250. Zero. Because it's double, I'll indicate it like this. And look, this is in the form of a constant, speed unit, komf. Yes, and let's print this BMW, let's see what result it gives us. Let's run this. Don't forget, if it's not selected in the run configuration, you have to run it like this. Yes, it's great. So, it directly shows me what the speed is, and also what its unit is. Well, what is the unit, what kind of speed does it show me? Yes. [Music] Now, let's quickly show you about the record class. So, a record class is better described when that class has immutable fields. For example, stop speed, I don't know, who would change this top speed? Because what you pass to the constructor initially will always be the same. So, I haven't seen it now, that a car is sold and its top speed changes later. So, it exists. That's why, let's say, where it says top speed here, let it be, what is it called, a record class. Yes, I'll delete this with your permission. And let's create a class here, of record type. This record was added from the 11th version, so a little late, because people probably said, oh dear, oh dear, and they introduced it. What is speed? And look what will happen. In the case of a record, we write the class like this. Instead of class, we write record. And here will be the description of the primary constructor. Well, what was the description of the primary constructor here? Double speed and unit, speed unit, unit. And look, I'm not writing anything else. Everything is already ready for it automatically. Are you crazy? Are you cold? So, what will happen automatically here? Let's write it as a comment. So, the following will happen here. The fields will be automatically written, I think they are private type, so they are private. Well, in short, I can even say a word. What will be written by the compiler in this record after such a description, but it's still better to write it physically, approximately. And the constructor, this primary constructor, will also be written like this. And its content will be written, the sun's spirit, well, what it is, in short, I'll just write dots. Then getters will be written, so getters, no, because it's final, yes. Getters for fields. Then equals will be written, hashcode too. And then the string version will also be written. Well, a primitive version for these fields. So, all, meaning what I wrote before, those will be added. Just this object of this class will be immutable, so to speak, meaning its fields cannot be changed. And now the next question for you should be, for example, in terms of usage, will anything change? Nothing will change. Just if the string makes slightly different cubes for these fields when printing, something square, you can override it. Remember, so you can override it and introduce your own version, for example, the string version. And the next question is, oh dear, Vaho, besides the primary constructor, can't you write another constructor? You can write another constructor. Compact, canonical, there are some options. Compact, it's written like this. Or let's write canonical. I think that's it. But if you write some other constructor option, of course, you will have to, for example, if it's a one-parameter constructor, assign a value to something for the second parameter, let's say the default unit is k/h. And well, this says that it saves, deletes, top speed. Look, there's only one constructor option. No, wait, why did it write to me? Delete it. Non-record delegate to. Another constructor must be called. This non-canonical description, or it must call my two-parameter one, pass speed and pass speed unit. And in this case, wherever I use this speed unit, I can stop specifying it because it's implicitly understood as kilometers per hour. You can see this option. So, a constructor is introduced with some other parameters than the primary one, but usually the primary one is enough. And these record classes are very good if you describe such immutable objects for which you don't want to write these banal methods by hand. That's all about this record, nothing special. You rarely encounter it because people don't use it, because it's part of the new version's syntax, and for new version syntax, meaning they usually write for the 8th version, or if it's code from an earlier version, they leave it the same. Let's say the 6th version was also popular, and if the code of the 6th version is written, they leave it in the 6th version's syntax. In case of update too. Yes, this was it, and it's just a theoretical issue related to what's written in the slides. Yes, we forgot about implementations. So, you can, in an enum, since an enum is like a class type, you can describe an abstract method in the enum class block, after the semicolon, and then each constant will override it with its own description in quotes. And the second option is to implement an interface. It's the same as taking an abstract method and again with the same syntax. Yes, for example, where gender is written, I can describe an abstract method here. For example, what should we call it now? Prefix, let's say string, name prefix, let's say prefixed name. And let it be abstract. So, let's write abstract here. And look what this will cause. We have errors here. So, this looks like a somewhat unusual syntax, but well, I'll explain it later in the next lesson, what it means. So, here, in such a block, you can specify the overriding part with each constant of the abstract method. Of course, this option distorts the code, because I look and think, oh dear, what's happening, but well, if you want, instead of introducing a field, you can write an abstract method for each one, and each of these abstract methods can say, let's say, I am male, mister, and this is, well, let's say, I don't know how it's written in the case of gender, or its, I don't know, let it be like this. So, we have this option. And if you implement an interface, similarly, for each one, you have to write these implementations. And here too, let's write this implementation that followed the abstract one in this block. So, we'll do this block like a class block, and inside, we'll override. But still, avoid this syntax of interfaces by enums, interface implementations, and abstract methods inside. Still avoid it, because there's no need for it, because then these upper constants will swell and swell. And as for me, yes, you can use this enum in a switch statement, but when you use it, for example, if you write switch here, switch, meaning when you do generations, you can do it without a prefix. This is not expressions, this is statements. So, you can, for example, mmn, well, you can think that since I'm referring to it here with a prefix, here too with a prefix. In the switch, the prefix is not written anymore. You can give me permission to write it here, but it's understood without a prefix that it refers to the constant of this gender type. So, if gender is male, or if gender is, for example, boy, this is cool, yes, case female, let's say, I am a woman, like a smiley face. And default is no longer needed because we've considered both cases. Yes, that's it. And let's run it, let's see what this does. Yes, for female, it said this. For male, it said this. So, here I just wanted to show that writing the prefix in switch statements is not necessary. Now let's look at the switch expression, meaning the expression syntax. That was also added in later versions, I think it was also somewhere around 11, 17, well, something like that. And switch expression, then it's like this, if we do this arrow, there's no break anymore, because the expression returns a result. Remember, yes? So, when I said that a statement and an expression differ, for example, a for loop block, an if block, an if-else block, a classic switch block returns nothing, it just performs some logic, so to speak, of the void type. And an expression returns something. For example, like a ternary if-else, a one-line one, yes, what they call ternary operations, or ternary operations. Look, like if gender equals, let's say, to genders, fine, and else, you are crazy. And now, when you look at this, and assignment can be done here. Yes, you can write something like, you can write, let's say, to save. And here you write something like this: text equals, well, now when a person looks at this, they think, wait, Vaho, can't this be written in one line, with a ternary comparison, yes? So, you can write this differently. Assignment, I don't know what you're telling me, but well, okay, you're not offering me another option. But I can write this like this. Look, equals, question mark, if true, is this remembered? If false, is this remembered? This syntax, question mark, this is an expression because it returns a result. And similarly, this will also return a result. But now, here, it can return no result, and be of void type. But it's better to return a result. If you use it, if you write an expression, everything should be in cases, everywhere. Yes, and here too, like this. Now, there's some error here. Remove expression. What does it want, man? This comma, am I making a mistake? Here too, like this. It didn't want this. I'll quickly search. I forget the syntax sometimes. Java Switch expression. Why is it written? It's in the 17th version of the language. Yes, maybe it was added in the 17th, that's why it's here. It shows me this in the 17th. Or let's look at this third one that's written. It's written in the 13th. Well, different. Yes, this is the documentation page on Qu. What's wrong with the internet? Yes, this is a good site, a blog by Badung. It has everything about Java libraries, Java. And in short, it's a very good tutorial page. Yes, this Badung site explains from the beginning what it's talking about, and then there are code examples. And somewhere here, yes, switch expression. And it's written directly like this. Oh, it's not wick, I wrote it correctly. Maybe I have to assign something. String language. Yes, you have to assign something. It seems to be throwing an error. And it ends with a semicolon because it's an expression. This also ends with a semicolon. And then you can simply print this message that you received from here. You can even put this here. If you are really, you know, if you don't want to introduce a variable, but in terms of readability, this code is a bit difficult to read. This is clearer. And look, what else is a distinguished feature of this switch expression? Yes, so, if I remove one case, which might exist, that option, because someone might be MF female. The compiler tells me it won't compile. Because it has to return a result. And in the case of female, you haven't written the result. And how can it compile? So, the code you give me will be nonsense, because what should we do in the case of female? That's why it forces me to write down all cases, or default. I don't know who I am. Yes, but we don't want this default. It's a very bad example. So, like this. So, we've also seen the switch expression. What is it called? In the case, and let's not drag it out too long. Yes, well, we can say, in one or two words, mention the commands related to Maven, and so on. So, Maven helps me manage my project. Well, it manages it for me. And management means, well, this sound shouldn't be turned off here. When I stand up, it means dependency management and the project building part, compilation, and packaging. And this is it. And this happens. So, Maven has thought out what to do first, then what the next stage should be, and then how to finish. So, this sequence is called the life cycle. So, the stages of the Maven process, so to speak, building. And we have this default life cycle. There are different life cycles. There is a side cycle, but this is the main one. Unfortunately, these are not used today, but you can still see them. And this is the clean part. So, the target folder. Remember, we talked about this before, if you don't delete the target folder and compile, build, build this Maven project after many changes, you will be left with previous results. And if you want to delete this target, you have to call the clean command. And the clean command runs from the clean life cycle, this clean phase. But the main thing is the commands related to these phases. And these phases are executed sequentially. After validate, compile, files, then checking tests. Tests were there. Then packaging. This will give us a jar file, meaning a zip file. And from the zip file, and then if it's called, it will do it and install it locally. In the local repository, where your built jar file will be, so to speak, your jar file. Yes, here. In your profile, in the dot m folder, there is the local repository where your project will fall in case of installation. Yes, something. Yes, we installed this jar file. And this jar file is the built jar file after the packaging phase, where your class files are directly placed. Yes, it's zipped, so to speak. Just remember this part. Yes, we talked about it in the first, second, something, second lesson. Yes, so, during compilation, Maven will compile, and IntelliJ will compile, and yes, it will put those class files here. And yes, it's enough to run all this from Java. But in real life, when you run something, it's good to have everything stored in one file and not have to transfer those classes, these classes, to the folder, or specify a million other class files in the classpath later, so that it runs and doesn't throw an error like "I don't know who this class is." That's a well-known error, a NullPointerException, when the JVM can't find the class during execution. And that's why they invented this way of zipping, meaning, let's zip it into one file. And just calling it zip, go and find out what's inside. And they just called the extension Java archive. And the Maven packaging phase gives me this jar file. So, the packaging phase of the default life cycle gives me my jar file. How to run this packaging phase? With the command mvn package. Here, in edit configuration, you add it. Well, you can do it from here, or you can do it from the console. For example, mvn, and what command do you want? Let's run clean. And after clean, let's run package. Clean will delete this target folder. It's a very primitive command. When you delete the target folder, then again, it waits for these phases, this, this, and this. Packaging will reach up to this point. Let's see anyway, because repetition is the mother of knowledge. Let's run this. And look, the command will be executed in the console. Where is the command, man? It's probably written at the end. Yes, clean package. But somewhere here, when we use Maven, it should be visible. But the phase is so large that nothing is visible. So, in short, mvn clean package will be executed. And look what happens. Clean was executed first. So, the clean plugin's clean command. Well, then some things were executed. Here's the compile file, compilation. After compilation is the testing part. And then is the packaging part. So, the jar plugin's jar command. And what does this tell me, Vaho? I built a jar file. And everything that is built is in this folder. The final jar file falls into the target folder. Intermediate files, resource files, class files, everything falls into this target. And here is our jar file. This is a zip. So, roughly remember it like this. Yes, and here is an additional folder, meta-inf, which tells you what the pom is. It creates the properties of your project. And some manifest, which simply tells you something, for example, the JDK specification, and something created by, and who created it. Maven Jar. And I can send this to you, for example. And you can then tell Maven to install it in the local repository. Because Maven is also a project, it's a plugin. Install. And you tell it to install this file locally. And then in your project, you can directly write in the dependency, my project's group ID, artifact ID, and since it's local, it will link to your project. And I just want you to remember that these phases of the default life cycle are executed sequentially. What each phase means, approximately. Local repository is just the local repo. Yes, it's on my local computer. And deploy means to release this file in a repository on a server. It doesn't mean launching a rocket at all. It's just installing in the remote repository. And then this is the site. Which used to be, well, this Maven has existed for a long time. And when they created it, it was very good, these static site generations. And let's say the information about the project exists in that file. And such a thing is called a site. And it has these commands. You can, for example, run this site command. Let's have fun anyway. It will give you static HTML pages about the project using the pom. Using the pom. And for this to work, I think it needs clean. It doesn't need clean. This has nothing to do with the project, classes, and so on. Yes, so, if we run the site, I think it will work. And if it doesn't work, you have to update the plugin, the site plugin. Because you are now thinking, Vaho is talking about plugins. And each phase works with plugins. And this plugin is also a Maven project. Yes, I mentioned that before. But it's a Maven version. We have versions, you know. Project versions. And where does it get the version to use by default? It's written in the parent pom, which is called super pom. Yes, the parent. It's connected to the parent. So, the super pom exists, where the default versions of plugins are written. And if something comes, well, I don't know, it stopped. And the internet is probably strange. And if the plugin is not used by default, and you think a new version is better, because you are on a new JDK, and so on, then you can override the version in the pom. Plugin. That's it. Or how is it? If something in the parent doesn't suit me, how do I change it? I have to override it. Yes, and here too, you can override the plugin version. And overriding happens here, in the build, in the plugins text. And then you can override plugins here. For example, I don't know which plugin to override, but well, some plugin. Let's look at Maven plugins. Let's say something. The internet probably did something because something. So, here you can override. Then by group ID, artifact ID, and version. Ah, that plugin, which was in the parent, well, a different version was written, an old version. This build text. We'll touch on this again in the next lesson. What happened? Did it do anything? So, it's loading. As you can see, it's writing many things. Look how many things it's writing. Well, the main poms are downloaded. Here, it writes poms, maybe it also writes jar files. Let's see, for example, jar, jar, jar. So, how many intermediate transitive dependencies. You see, for plugins. And there's a problem. Yes. Well, let's update this site plugin. So, let's come here and write Java Maven Site plugin. This is also on the Maven repository, people. Yes, so Maven does operations with its own projects. It's written on Java. Yes, it's written on Java itself. And it builds Java projects. And it also uses its own projects written by itself to build. So, it is. Like the first compiler, when it was created, and other compilers were created with that previous compiler. So, it's like an inception. So, you can see this plugin. And it's also on the repository. And let's specify the latest version. Here, 2024. I don't know why they update it, but people use it for something. Well, for fun, it's good to do these things and still see plugin management. Something else. Plugin. Like this, more precisely. I'll write this. But here, plugin must be written. Now, this will be fetched again. Its transitives too. So, this has to be downloaded once locally. And then you won't need it anymore. You can click on this without refreshing. And during Maven build, it will fetch this. Now, it's not visible here if it's fetched or not. Yes, look, it downloaded some things and generated build success. And what did it generate? Then what happens? Where is my site? Here it is. In this site folder. Look, static files with its CSS and some Javascript. I just don't know what it's used for. And if you open index.html, you'll see. Ah, Maven project sites were exactly in this style. Yes, I don't know. This is my project's name. [Music] In dependencies, it's written what I depend on. In the Maven coordinate, it's written what the group ID and artifact are. In short, it gave me static pages about my project. This Maven site command, from this site cycle. So, this is just to delete the target folder. This command is mainly used. This phase is used with this command. And these are the main phases for building and running the project, and for deployment, and so on. And this is just some remaining site generation. And mainly, we use this. I wanted you to know this theoretically. And then it talks about plugins. And just remember these commands. So, if you want to clean, you can use the combination clean package. Clean install. Compile. For compilation only, this will give you only the class folder with compiled class files in the target. Test. Just after this, it will do the test phase and run the tests. After passing the tests, it works. Then package. It will give me a jar file. Then, if you want to install it locally, it will do that. And then, if you want to deploy the locally installed one to a server, it will do that. The deploy command. I have deployed. You can also, so, if you have a very cool project, a cool library, and you want to share it with people, you can put it on the central Maven repository. Just when you put it, you have to do this deploy. And when you put it, I think it won't let you put it directly on some repo. You do this deploy to some repo, and then you put it on the central one. It will appear on the central one. I tried, but then I got lazy. It's very complicated. So, try it yourself if you want to do this central repository deploy. But like, like Google Play, or what is it called, Play Store. Yes, so, when you put something, it's checked in some way, so that you don't put nonsense. Because someone might put a potato library, and why should it be there? It's better to be something normal. Yes, that's all. So, I'll turn off the recording now. So.