Hi! In this lesson, we'll talk about how abstract classes differ from interfaces and consider some examples with common abstract classes.
We've devoted a separate lesson to the differences between an abstract class and an interface, because this topic is very important. You'll be asked about the difference between these concepts in 90% of future interviews. That means you should be sure to figure out what you're reading. And if you don't fully understand something, read additional sources.
So, we know what an abstract class is and what an interface is. Now we'll go over their differences.
…you don't have to use
In this example, we read data from a file located on a computer at 'D:/Users/UserName/someFile.txt'. We create 2 objects — a
- An interface only describes behavior. It has no state. But an abstract class includes state: it describes both.For example, take the
Bird
abstract class and theCanFly
interface:Let's create aMockingJay
bird class and make it inheritBird
:As you can see, we can easily access the abstract class's state — itsspecies
andage
variables.But if we try to do the same with an interface, the picture is different. We can try to add variables to it:We can't even declare private variables inside an interface. Why? Because the private modifier was created to hide the implementation from the user. And an interface has no implementation inside it: there isn't anything to hide.An interface only describes behavior. Accordingly, we can't implement getters and setters inside an interface. This is the nature of interfaces: they are needed to work with behavior, not state.Java 8 introduced default methods for interfaces that have an implementation. You already know about them, so we won't repeat ourselves. - An abstract class connects and unites classes that are very closely related. In the same time, a single interface can be implemented by classes that have absolutely nothing in common.Let's return to our example with birds.Our
Bird
abstract class is needed for creating birds that are based on that class. Just birds and nothing else! Of course, there will be different kinds of birds.With theCanFly
interface, everybody gets on in their own way. It only describes the behavior (flying) associated with its name. Many unrelated things 'can fly'.These 4 entities are not related to each other. They aren't even all living. However, they allCanFly
.We couldn't describe them using an abstract class. They don't share the same state or identical fields. To define an aircraft, we would probably need fields for the model, production year, and maximum number of passengers. For Carlson, we would need fields for all the sweets he ate today, and a list of the games he'll play with his little brother. For a mosquito, ...uh... I don't even know... Maybe, an 'annoyance level'? :)The point is that we can't use an abstract class to describe them. They are too different. But they do have shared behavior: they can fly. An interface is perfect for describing everything in the world that can fly, swim, jump, or exhibit some other behavior. - Classes can implement as many interfaces as you want, but they can only inherit one class.We've already mentioned this more than once. Java doesn't have multiple inheritance of classes, but it does support multiple inheritance of interfaces. This point follows in part from the previous one: an interface connects many different classes that often have nothing else in common, while an abstract class is created for a group of very closely related classes. Therefore, it makes sense that you can only inherit one such class. An abstract class describes an 'is-a' relationship.
Standard interfaces: InputStream and OutputStream
We've already gone over various classes responsible for input and output streams. Let's considerInputStream
and OutputStream
.
In general, these aren't interfaces at all, but rather entirely genuine abstract classes. Now you know what that means, so it will be much easier to work with them :)
InputStream
is an abstract class responsible for byte input. Java has several classes that inherit InputStream
. Each of them is designed to receive data from different sources.
Because InputStream
is the parent, it provides several methods that make it easy to work with data streams. Each descendant of InputStream
has these methods:
int available()
returns the number of bytes available for reading;close()
closes the input stream;int read()
returns an integer representation of the next available byte in the stream. If the end of the stream has been reached, -1 will be returned;int read(byte[] buffer)
tries to read bytes into buffer, and returns the number of bytes read. When it reaches the end of the file, it returns -1;int read(byte[] buffer, int byteOffset, int byteCount)
writes part of a block of bytes. It is used when the byte array may not have been filled entirely. When it reaches the end of the file, it returns -1;long skip(long byteCount)
skips byteCount bytes in the input stream, and returns the number of bytes ignored.
FileInputStream
: the most common type ofInputStream
. It is used to read information from a file;StringBufferInputStream
: Another helpful type ofInputStream
. It converts a string into anInputStream
;BufferedInputStream
: A buffered input stream. It is used most often to increase performance.
BufferedReader
and said that you don't have to use it?
When we write:
…you don't have to use
BufferedReader
: An InputStreamReader
can do the job. But BufferedReader
improves the performance and can also read whole lines of data rather than individual characters.
The same thing applies to BufferedInputSteam
! The class accumulates input data in a special buffer without constantly accessing the input device.
Let's consider an example:
In this example, we read data from a file located on a computer at 'D:/Users/UserName/someFile.txt'. We create 2 objects — a
FileInputStream
and a BufferedInputStream
that 'wraps' it. Then we read bytes from the file and convert them into characters. And we do that until the file ends.
As you can see, there's nothing complicated here. You can copy this code and run it on a real file on your computer :)
The OutputStream
class is an abstract class that represents an output stream of bytes.
As you already know, this is the opposite of an InputStream
. It isn't responsible for reading data from somewhere, but rather for sending data somewhere.
Like InputStream
, this abstract class gives all of its descendants a set of convenient methods:
int close()
closes the output stream;void flush()
clears all output buffers;abstract void write(int oneByte)
writes 1 byte to the output stream;void write(byte[] buffer)
writes a byte array to the output stream;void write(byte[] buffer, int offset, int count)
writes a range of count bytes from an array, starting at the offset position.
OutputStream
class:
DataOutputStream
. An output stream that includes methods for writing standard Java data types.A very simple class for writing primitive Java data types and strings. You'll probably understand the following code even without an explanation:It has separate methods for each type —writeDouble()
,writeLong()
,writeShort()
, and so on.FileOutputStream
. This class implements a mechanism for sending data to a file on disk. By the way, we already used it in the last example. Did you notice? We passed it to DataOutputStream, which acted as a 'wrapper'.BufferedOutputStream
. A buffered output stream. There's also nothing complicated here. It's purpose is analogous toBufferedInputStream
(orBufferedReader
). Instead of the usual sequential reading of data, it writes data using a special 'cumulative' buffer. The buffer makes it possible to reduce the number of times the data sink is accessed, thereby increasing performance.Again, you can play around with this code yourself and verify that it will work on real files on your computer.
FileInputStream
, FileOutputStream
and BuffreredInputStream
, so this is enough information for a first acquaintance.
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.