This page mainly deals with Java / Swift notation of "class implementation", "class inheritance", and "class design". This article is based on 1.7 for Java and Swift3 for Swift, but I'm sorry if there is a notation mistake.
-Comparison between Java and Swift (1) Source control / Scope / Variables -Comparison between Java and Swift (2) Basic type / Arithmetic expression / Control syntax / Function definition -[Comparison between Java and Swift (3) Class implementation / Class inheritance / Class design]
The following class notation is described.
** Class design **
--Employee class --Has the following properties --Name: String type --Gender: Enumerated constants --Age: Numerical value --Implemented an instance method for self-introduction that can be called from an external class
Java
python
/**
*Employee class
*/
public class Employee {
/**
*name
*/
protected String name;
/**
*sex
*/
protected Sex sex;
/**
*age
*/
protected int age;
/**
*constructor
*
* @param name name
* @param sex gender
* @param age age
*/
public Employee(String name, Sex sex, int age) {
this.name = name;
this.sex = sex;
this.age = age;
}
/**
*constructor
*/
public Employee() {
this.name = "";
this.sex = Sex.Unknown;
this.age = 0;
}
/**
*Self-introduction
*
* @return Self-introduction text
*/
public String selfIntroduction() {
String value = "";
value += "name:=" + this.name + ", ";
value += "age:=" + this.age + ", ";
value += "sex:=" + this.sex + ", ";
return value;
}
/**
*Gender enum
*/
public enum Sex {
Man("Man"),
Woman("woman"),
Unknown("unknown");
private String value;
Sex(String value) {
this.value = value;
}
}
}
python
Employee employee = new Employee(); //Instance generation
String value = employee.selfIntroduction(); //Instance method call
System.out.print(value);
Swift
python
class Employee {
///Gender enum
enum Sex:String {
case Man = "Man"
case Woman = "woman"
case Unknown = "unknown"
}
///name
var name:String
///sex
var sex:Sex
//age
var age:Int
///Initializer
init(name:String = "", age:Int = 0, sex:Sex = Sex.Unknown) {
self.name = name
self.sex = sex
self.age = age
}
//Self-introduction
func selfIntroduction() -> String {
var value:String = ""
value += "name:=" + self.name + ", "
value += "age:=" + self.age.description + ", "
value += "sex:=" + self.sex.rawValue + ", "
return value
}
}
python
let employee = Employee() //Instance generation
let value = employee.selfIntroduction() //Instance method call
print(value)
The following class notation is described.
** Class design **
--Programmer class that inherits the Employee class --Has the following properties --Position: Enumerated constant --Implementation of a method that overrides the instance method for self-introduction of the Employee class, which is the base class. --Implementation of a method to calculate salary according to position and age
Java
--In Java, like Swift, multiple inheritance is not allowed and there is only one base class. --When inheriting, write "class class name extends base class name {...}". --In Java, method override is performed by implementing the method with the same method name, argument type, and number of arguments as the base class in the inherited class. --It is recommended to add the @Override annotation to indicate that the method will be overridden. --In Java, there is no Computed property, and getters, setters, etc. are represented by methods.
/**
*Programmer class
*/
public class Programmer extends Employee {
/**
*Position
*/
private JobTitle jobTitle;
/**
*constructor
*
* @param jobTitle Position
* @param name name
* @param sex gender
* @param age age
*/
public Programmer(JobTitle jobTitle, String name, Sex sex, int age) {
super(name, sex, age);
this.jobTitle = jobTitle;
}
/**
*Self-introduction
*
* @return Self-introduction text
*/
@Override
public String selfIntroduction() {
String value = super.selfIntroduction();
value += "jobTitle:=" + this.jobTitle + ", ";
return value;
}
/**
*Payroll
* @return salary
*/
public int salary() {
int jobSalary;
switch (this.jobTitle) {
case A1:
jobSalary = 340000;
break;
case A2:
jobSalary = 300000;
break;
case B1:
case B2:
jobSalary = 260000;
break;
case C1:
case C2:
jobSalary = 220000;
break;
case D1:
case D2:
jobSalary = 180000;
break;
default:
jobSalary = 0;
}
int ageSalary;
//Since it is not possible to describe an expression in the evaluation result of switch in Java, it is calculated by if statement.
if (super.age >= 0 && super.age < 22) {
ageSalary = 0;
} else if (super.age >= 22 && super.age < 28) {
ageSalary = 20000;
} else if (super.age >= 28 && super.age < 34) {
ageSalary = 40000;
} else if (super.age >= 34 && super.age < 40) {
ageSalary = 40000;
} else if (super.age >= 40 && super.age < 100) {
ageSalary = 20000;
} else {
ageSalary = 0;
}
return jobSalary + ageSalary;
}
/**
*Position enum
*/
public enum JobTitle {
A1,
A2,
B1,
B2,
C1,
C2,
D1,
D2;
}
}
python
Programmer programmer = new Programmer(Programmer.JobTitle.A1, "Marie", Employee.Sex.Woman, 30); //Instance generation
String value = programmer.selfIntroduction(); //Instance method call
int salary = programmer.salary(); //Call payroll method
System.out.print(value);
Swift
--Swift, like Java, does not allow multiple inheritance and has only one base class. --When inheriting, write "class class name: base class name {...}". --In Swift, methods are overridden by implementing a method in the inherited class that has an "override" modifier in the method name that matches the base class. --In Swift, there is a Computed property that provides getters and setters for properties.
python
///Programmer
class Programmer:Employee {
///Position enum
enum JobTitle:Int {
case A1 = 1
case A2 = 2
case B1 = 3
case B2 = 4
case C1 = 5
case C2 = 6
case D1 = 7
case D2 = 8
case Unknown = 0
}
///Position
var jobTitle:JobTitle;
///name
var salary:Int {
get {
var jobSalary = 0
switch self.jobTitle {
case JobTitle.A1:
jobSalary = 34-0000
case JobTitle.A2:
jobSalary = 30-0000
case JobTitle.B1, JobTitle.B2:
jobSalary = 26-0000
case JobTitle.C1, JobTitle.C2:
jobSalary = 22-0000
case JobTitle.D1, JobTitle.D2:
jobSalary = 18-0000
default:
jobSalary = 0
}
var ageSalary = 0
switch self.age {
case 0...22:
ageSalary = 0-0000
case 22...28:
ageSalary = 2-0000
case 28...34:
ageSalary = 4-0000
case 34...40:
ageSalary = 4-0000
case 40...100:
ageSalary = 2-0000
default:
ageSalary = 0
}
return jobSalary + ageSalary
}
}
///Initializer
init(jobTitle:JobTitle = JobTitle.Unknown) {
self.jobTitle = jobTitle
super.init()
}
//Self-introduction
override func selfIntroduction() -> String {
var value = super.selfIntroduction()
value += "jobTitle:=" + self.jobTitle.rawValue.description + ", "
return value
}
}
let programmer = Programmer(jobTitle: Programmer.JobTitle.Unknown) //Instance generation
let value = programmer.selfIntroduction() //Instance method call
let salary = programmer.salary //Calling the Payroll Computed property
print(value)
print(salary)
The following is a brief explanation of Java and Swift's unique specifications and how to use them when designing classes.
Java
Java has the idea of effectively defining the three major object-oriented elements (encapsulation, inheritance, and polymorphism) called abstract classes. Unlike so-called ordinary classes, abstract classes, as the name implies, are abstract and cannot be instantiated. Superheroes are real, but classes that represent as abstract as justice cannot.
To declare an abstract class, prefix the class name with the modifier "abstract", such as "abstract class abstract class name {...}". An outline of processing and common properties are defined in the abstract class, and specific processing is described in the subclass that inherits the abstract class.
/**
*Justice abstract class
*/
public abstract class AbstractJustice {
/**
*Basic ability
*/
protected int mBasicAbility;
/**
*Potential
*/
protected int mPotentialCapacity;
/**
*Processing to save
*/
public abstract void save();
/**
*Basic ability acquisition
*
* @return basic ability
*/
public int getBasicAbility() {
return mBasicAbility;
}
/**
*Potential acquisition
*
* @return potential
*/
public int getPotentialCapacity() {
return mPotentialCapacity;
}
/**
*combat
*
* @param enemyAbility Enemy ability
* @return battle result true...Victory, false...defeat
*/
public boolean fight(int enemyAbility) {
int basicAbility = getBasicAbility();
if (basicAbility > enemyAbility) {
//Win if your basic ability is exceeded
return true;
}
//Basic ability+Potential*Win if the random coefficient is above, defeat if below
int potentialCapacity = getPotentialCapacity();
float coefficient = new java.util.Random().nextFloat();
return basicAbility + potentialCapacity * coefficient > enemyAbility;
}
}
/**
*Anpanman class
*/
public class Anpanman extends AbstractJustice {
/**
*Initial basic ability
*/
private int INIT_BASIC_ABILITY = 10;
/**
*Initial potential
*/
private int INIT_POTENTIAL_CAPACITY = 3;
/**
*constructor
*/
public Anpanman() {
mBasicAbility = INIT_BASIC_ABILITY;
mBasicAbility = INIT_POTENTIAL_CAPACITY;
}
@Override
public void save() {
System.out.println("Eat face");
//Feeding the face lowers basic abilities but increases potential
mBasicAbility--;
mPotentialCapacity++;
//When the basic ability becomes 3 or less, Batako will change her face, so it will return to the original
if (mBasicAbility <= 3) {
//\ Anpanman! A new face! !! /
mBasicAbility = INIT_BASIC_ABILITY; //<Energetic 100 times Anpanman! !!
}
}
@Override
public boolean fight(int enemyAbility) {
//Anpanman has a victory correction, so it becomes an enemy ability-10
enemyAbility -= 10;
return super.fight(enemyAbility);
}
}
Prior to Java 8, methods could only be defined as instance methods in an interface, but since Java 8 it is now possible to implement static methods in an interface as well. In addition, the idea of default method has been added, and the processing body of the method can be implemented in the interface.
The interface in Java describes the outline of the process, and you can think of it as a function in which only the abstract methods of the abstract class are aggregated. Although there are differences due to differences in the protocol and language specifications in Swift, it can be considered that they are similar. However, as the name of the interface as a function indicates, it is a summary of processing and conventions, so it cannot be instantiated and cannot have member variables as properties. "Operation of Gundam" itself has no color or shape, and it has the same meaning as having color or shape in Gundam itself. (I'm sorry if anyone likes Gundam ...)
Also, interfaces are different from class inheritance, and classes can implement multiple interfaces. To declare an interface, write "interface interface name {...}". In the interface, you can write methods that do not describe processing blocks that only outline processing, and static constants only.
The outline of the process and the expected result are defined, but the process content is handled by the class that implements the interface, and when implementing the specified interface, it is necessary to implement all the functions of that interface.
python
/**
*Gundam operation
*/
public interface GundamOperation {
/**
*Speed up
*/
void speedUp();
/**
*Speed down
*/
void speedDown();
/**
*Beam saver equipment
*/
void equipmentSaber();
/**
*Beam saver release
*/
void removeSaber();
/**
*Gun shooting
*/
void shooting();
}
/**
*∀ Gundam class
*/
public class GundamTurnA implements GundamOperation {
@Override
public void speedUp() {
System.out.println("Speed up");
}
@Override
public void speedDown() {
System.out.println("Speed down");
}
@Override
public void equipmentSaber() {
System.out.println("Beam saver equipment");
}
@Override
public void removeSaber() {
System.out.println("Beam saver release");
}
@Override
public void shooting() {
System.out.print("Gun shooting");
}
}
/**
*Zaku class
*/
public class Zaku implements GundamOperation {
@Override
public void speedUp() {
System.out.println("Speed up");
}
@Override
public void speedDown() {
System.out.println("Speed down");
}
@Override
public void equipmentSaber() {
System.out.println("Beam saver equipment");
}
@Override
public void removeSaber() {
System.out.println("Beam saver release");
}
@Override
public void shooting() {
System.out.print("Gun shooting");
}
}
At this time, the merit of using the interface is that the target interface is implemented = the operation provided as the interface is guaranteed. Whatever the class is, providing an interface allows for flexible implementation.
GundamTurnA gundamTurnA = new GundamTurnA();
Zaku zaku = new Zaku();
shooting(gundamTurnA);
shooting(zaku);
private void shooting(GundamOperation gundamOperation) {
gundamOperation.shooting(); //Can be operated as an interface
}
Swift
Extensions can be used to extend existing classes that Swift does not have in Java. What a class provided by the library is also possible (!)
print(10.hex)
extension Int {
///Hexadecimal
var hex: String {
return String(self, radix: 16)
}
///8 base
var oct: String {
return String(self, radix: 8)
}
///Binary number
var bin: String {
return String(self, radix: 2)
}
///JP tax rate
static func jpTaxRate() -> Double {
return 0.8
}
///JP tax-included amount
func amount() -> Double {
return Int.jpTaxRate() * Double(self)
}
}
However, you cannot do the following.
--Definition of properties other than Computed property --Override of already implemented methods
The protocol in Swift describes the outline of the process, and it can be considered that it is similar, although there are differences due to the difference in the interface and language specifications in Java. However, as the name of the protocol as a function indicates, it is a summary of processing and conventions, so it cannot be instantiated and cannot have member variables as properties.
Also, the Java interface can have static constants (eg "static final String HOGE =" hoge ""), but the protocol does not support it and can only provide functions and Computed properties. To declare a protocol, write "protocol protocol name {...}". Only the Computed property of the getter method / setter method that does not describe the processing block and the method that does not describe the processing block can be described in the protocol. The outline of the process and the expected result are defined, but the process content is handled by the class that implements the protocol.
///Read delegate protocol
protocol ReadDelegate {
///Read process
func read() -> Int
}
///Progress protocol
protocol Progressing {
///Total amount
var total: Int { get }
///Completion amount
var completed: Int { get set }
func read()
}
///String conversion protocol
protocol StringTranslatable {
///String conversion
var asString: String{ get }
}
class Comic : StringTranslatable, Progressing {
var author:String = ""
var title:String = ""
var text:String = ""
var readDelegate:ReadDelegate?
let rawTotal:Int = 300
var rawCompleted:Int = 0
var asString: String {
get {
return "author:=" + author + "\n"
+ "title:=" + title + "\n"
+ "text:=" + text + "\n"
}
}
var total: Int {
get {
return rawTotal
}
}
var completed: Int {
get {
return rawCompleted
}
set {
rawCompleted = newValue
}
}
func read() {
if (readDelegate != nil) {
let readPage = readDelegate?.read()
completed += readPage!
}
}
}
///This read delegate protocol implementation class
class BookReadDelegate:ReadDelegate {
func read() -> Int {
return 5
}
}
At this time, the merit of using the protocol is that the target protocol is implemented = the operation provided as the protocol is guaranteed.
As already described in the "Book" class above, the processing of the "read ()" function is delegated to "BookReadDelegate", and whatever the class is, the protocol is provided. Allows for flexible implementation.
Also, in the argument of the function etc., specify "Variable name: protocol
let comic = Comic()
comic.title = "El extranjero"
comic.author = "Albert Camus"
comic.text = "L'Etranger has the force and fascination of myth......"
comic.readDelegate = BookReadDelegate() //Set a class that implements ReadDelegate to delegate processing
readBook(comic)
func readBook(target:protocol<Progressing, StringTranslatable>) { //Implemented by Progressing, StringTranslatable
print(target.asString)
target.read()
print(target.completed)
}
Among the features that Swift does not have in Java, existing classes can be extended to conform to the protocol. To extend an existing class with a protocol, write "extension existing class name: extension target protocol name {...}". In the example below, the "Int" class is extended with the "StringTranslatable" created above, and the processing details of the "asString" Computed property, which is the implementation requirement of "StringTranslatable", are implemented.
///Extend Int with StringTranslatable
extension Int: StringTranslatable {
var asString: String {
get {
return "This number is[" + description + "]is."
}
}
}
A subscript is a subscript expression used to access an array or dictionary element. Swift allows you to implement subscripts in structs, enums, and classes.
var test = Test()
print(test["A"]) // "1"And output
class Test {
let values = ["A":"1", "B":"2", "C":"3", "D":"4"]
subscript(param:String) -> String {
get {
return self.values[param]!
}
}
}
Swift allows you to overload existing operators. Operator overloads can be defined as global functions to give them unique behavior.
struct Test {
var count:Int = 0
}
struct SumTest {
var count:Int = 0
}
func + (left: Test, right: Test) -> SumTest {
let sum = left.count + right.count
return SumTest(count: sum)
}
let hoge1 = Test(count: 1)
let hoge2 = Test(count: 1)
let add = hoge1 + hoge2
print(add) // SumTest(count: 2)
Recommended Posts