JetBrains Academy: Interfaces - Kamil-Jankowski/Learning-JAVA GitHub Wiki
JetBrains Academy: Interfaces
Mutable geometric shapes:
Suppose, you are writing a geometric engine. Now it includes classes and interfaces Circle
, Rectangle
, Movable
and Scalable
.
You need:
- to write a new interface
MutableShape
that extends both existing interfaces; - to implement the new interface by each class;
- to override methods
move
andscale
in both classes:scale
should multiply theradius
of a circle by the specifiedfactor
;scale
should multiplywidth
andheight
of a rectangle by the specifiedfactor
;move
should adddx
anddy
to the center of a circle;move
should adddx
anddy
to the upper-left corner of a rectangle.
See the provided code and read comments to understand your task better. Now the code is not compiled.
Note:
- do not remove existing classes and their members (including getters and constructors).
- do not make your classes and interfaces
public
.
After your changes, the following code should be compiled:
MutableShape circle = new Circle(2.0f, 3.5f, 10.1f);
circle.move(10.1f, 20.2f);
circle.scale(2.2f);
((Circle) circle).getRadius();
interface Movable {
void move(float dx, float dy);
}
interface Scalable {
void scale(float factor);
}
interface MutableShape extends Movable, Scalable {
}
final class Circle implements MutableShape {
// Defines the horizontal position of the center of the circle
private float centerX;
// Defines the vertical position of the center of the circle
private float centerY;
// Defines the radius of the circle
private float radius;
public Circle(float centerX, float centerY, float radius) {
this.centerX = centerX;
this.centerY = centerY;
this.radius = radius;
}
public float getCenterX() {
return centerX;
}
public float getCenterY() {
return centerY;
}
public float getRadius() {
return radius;
}
@Override
public void move(float dx, float dy){
centerX += dx;
centerY += dy;
}
@Override
public void scale(float factor){
radius *= factor;
}
}
final class Rectangle implements MutableShape {
// Defines the X coordinate of the upper-left corner of the rectangle.
private float x;
// Defines the Y coordinate of the upper-left corner of the rectangle.
private float y;
// Defines the width of the rectangle.
private float width;
// Defines the height of the rectangle.
private float height;
public Rectangle(float x, float y, float w, float h) {
this.x = x;
this.y = y;
this.width = w;
this.height = h;
}
public float getX() {
return x;
}
public float getY() {
return y;
}
public float getWidth() {
return width;
}
public float getHeight() {
return height;
}
@Override
public void move(float dx, float dy){
x += dx;
y += dy;
}
@Override
public void scale(float factor){
height *= factor;
width *= factor;
}
}
Account Service:
You are given an interface named AccountService
. The interface has two abstract methods:
findAccountByOwnerId(long id)
that returnsAccount
found by owner id ornull
.countAccountsWithBalanceGreaterThan(long balance)
that returns the number of accounts with the balance greater than the passed value. There are also two other classes:Account
(id, balance, owner) andUser
(id, firstName, lastName). See their implementations in the provided code template.
You need to implement the AccountService
interface and its two methods. Your implementation should be named AccountServiceImpl
. It should have a constructor with one argument — an array of accounts. The implementation must keep the array inside. The first method should search for an account by owner id in the array, the second one — count the number of accounts that meet the given condition in the array.
Here's an example of an instance:
Account[] accounts = ...
AccountService service = new AccountServiceImpl(accounts);
interface AccountService {
/**
* It finds an account by owner id
* @param id owner unique identifier
* @return account or null
*/
Account findAccountByOwnerId(long id);
/**
* It count the number of account with balance > the given value
* @param value
* @return the number of accounts
*/
long countAccountsWithBalanceGreaterThan(long value);
}
// Declare and implement your AccountServiceImpl here
class AccountServiceImpl implements AccountService{
private Account[] arrayOfAccounts;
public AccountServiceImpl(Account[] accounts){
this.arrayOfAccounts = accounts;
}
@Override
public Account findAccountByOwnerId(long id) {
for (Account acc: arrayOfAccounts){
if(acc.getOwner().getId() == id){
return acc;
}
}
return null;
}
@Override
public long countAccountsWithBalanceGreaterThan(long value) {
long counter = 0;
for (Account acc : arrayOfAccounts){
if(acc.getBalance() > value){
counter++;
}
}
return counter;
}
}
class Account {
private long id;
private long balance;
private User owner;
public Account(long id, long balance, User owner) {
this.id = id;
this.balance = balance;
this.owner = owner;
}
public long getId() { return id; }
public long getBalance() { return balance; }
public User getOwner() { return owner; }
}
class User {
private long id;
private String firstName;
private String lastName;
public User(long id, String firstName, String lastName) {
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
}
public long getId() { return id; }
public String getFirstName() { return firstName; }
public String getLastName() { return lastName; }
}
Compact strings with AsciiCharSequence:
Write a class named AsciiCharSequence
that implements compact storage of ASCII-character sequences. Their codes can be stored in one single byte, unlike Unicode characters. Compared to the standard String class, your class will require twice less memory (before Java 9).
The class AsciiCharSequence
should:
- implement the interface
java.lang.CharSequence
; - have a constructor that takes a byte array;
- define methods
length
,charAt
,subSequence
, andtoString
. You can see the declaration of methods and their behavior in the description ofjava.lang.CharSequence
(JavaDoc or sources).
public class AsciiCharSequence implements CharSequence{
private byte[] sequence;
public AsciiCharSequence(byte[] args){
this.sequence = args;
}
@Override
public int length() {
return sequence.length;
}
@Override
public char charAt(int index) {
return (char) sequence[index];
}
@Override
public CharSequence subSequence(int start, int end) {
byte[] subSequence = new byte[end-start];
for (int i = 0; i < subSequence.length; i++) {
subSequence[i] = sequence[start+i];
}
return new AsciiCharSequence(subSequence);
}
@Override
public String toString(){
char[] charSequence = new char[sequence.length];
for(int i = 0; i < sequence.length; i++){
charSequence[i] = (char) sequence[i];
}
return String.valueOf(charSequence);
}
}