How to extract abstraction? - oop

My question is trivial, but i can not find proper solution.
Code (just for example):
public class ToRefact
{
public int Func1(int i)
{
int a = i;
a++;
a++;
a++;
int b = FuncX2(a); //b = a * 2;
b++;
b++;
b++;
return a + b;
}
public int Func2(int i)
{
int a = i;
a++;
a++;
a++;
int b = FuncX3(a); // b = a * 3;
b++;
b++;
b++;
return a + b;
}
private int FuncX2(int b)
{
return b * 2;
}
private int FuncX3(int b)
{
return b * 3;
}
}
We can see, func1 and func2 has same body, except of middle of code: differences is FuncX2 and FuncX3. But, i can not do base abstract class because this code in the middle!
How can i do common abstraction? Please, do not change operations (3 times a++, 3 times b++) and do not change sequence
Thanks

Assuming your language of choice can pass around "pointers" to functions:
public class ToRefact
{
private int Func(int i, Func<int, int> f)
{
int a = i;
a++;
a++;
a++;
int b = f(a); //b = a * 2;
b++;
b++;
b++;
return a + b;
}
public int Func1(int i)
{
return Func(i, FuncX2);
}
public int Func2(int i)
{
return Func(i, FuncX3);
}
private int FuncX2(int b)
{
return b * 2;
}
private int FuncX3(int b)
{
return b * 3;
}
}

You could use template method (or even strategy pattern depending on real scenario) but in this simple case I would do something like this:
public class ToRefact
{
public int Func1(int i)
{
int a = FuncAdd3(i);
int b = FuncX2(a); //b = a * 2;
b = FuncAdd3(b);
return a + b; // Or more compact FuncAdd3(i) + FuncAdd3(FuncX2(FuncAdd3(i)))
}
public int Func2(int i)
{
int a = FuncAdd3(i);
int b = FuncX3(a); //b = a * 2;
b = FuncAdd3(b);
return a + b; // Or more compact FuncAdd3(i) + FuncAdd3(FuncX3(FuncAdd3(i)))
}
private int FuncAdd3(int b)
{
return b + 2;
}
private int FuncX2(int b)
{
return b * 2;
}
private int FuncX3(int b)
{
return b * 3;
}
}

Alternatively you could create a more modular and testable approach.
Create ICalculator interface like:
public interface ICalculator
{
int Calculate(int a);
}
And two concrete implementations
public class CalculatorX : ICalculator
{
public int Calculate(int a)
{
return a * 2;
}
}
public class CalculatorY : ICalculator
{
public int Calculate(int a)
{
return a * 3;
}
}
Then you would accept this as a parameter:
public int Func1(ICalculator calculator)
{
int a = i;
a++;
a++;
a++;
int b = calculator(a);
b++;
b++;
b++;
return a + b;
}
And call it like:
var calculatorX = new CalculatorX();
var result = Func1(calculatorX );
This makes it easy to replace implementations, mock them out, even inject them using your favorite IoC container. You also explicitly specify the contract of your method, so that if you ever have to add a new implementation, you know what to implement thanks to the interface.

public class ToRefact{
public int Func1(int i){
int a = i;
a = addThree(a);
int b = FuncX2(a); //b = a * 2;
b = addThree(b);
return a + b;
}
public int Func2(int i){
int a = i;
a = addThree(a);
int b = FuncX3(a); // b = a * 3;
b = addThree(b);
return a + b;
}
private int FuncX2(int b){
return b * 2;
}
private int FuncX3(int b){
return b * 3;
}
private int addThree(int x){
x++;
x++;
x++;
return x;
}
}

You can create a base class and apply the template method design pattern.
Example
note that I've used Delphi as that's easiest for me to write from memory but the intent is the same in every language that has virtual and abstract methods
TCustomRefact = class(TObject)
protected
function Calculate;
function Multiply(const Value: Integer); virtual; abstract;
end;
TRefact1 = class(TCustomRefact )
protected
function Multiply(const Value: Integer); override;
end;
TRefact2 = class(TCustomRefact )
protected
function Multiply(const Value: Integer); override;
end;

Related

Arduino - passing values by reference from lamda to singleton

Hello i am bigginer in programing and i have specific problem.
I have been learning a new ways to write a code in small Arduino project.
that project have multiple objects like distance measuring Senzor, led diods , temperature senzor, etc. And all this objects have its own menu where you can, for example, start a calibration or just get values.
What i need is singleton class that has a function enter_esc() that need a int (*funct)() parameter basically function pointer.
That enter_esc(int (*funct)()) function just looping function until you press escape pin which is defined.
function Calibration() have inside some private: object data types like value or cali_value.
so i tried to insert function Calibration() right into enter_esc(Calibration) but it won't compile becouse i didnt pass that vlaues by reference or copy.
but what i found is lambda.
i made a lamda similar to a Calibration() function and i passed values by reference &{//domething;}
but i had to use enter_esc(std::function<int()>& funct) whitch is only int C++ standard library and not in Arduino C/C++ so my qestion is:
[is there some way how to pass values by reference by using lambda to a singleton class in Arduino ?]
(i konw it can be done differently but like i said i want to learn some new ways to program, also if you have some different way to make it i will by very happy to see it)
10Q for your time :)
//Class.h
#pragma once
class events {
private:
static events e_instance;
int p_menu, p_enter, p_esc, p_up, p_down;
int menuValue;
events();
public:
events(const events&) = delete;
static events& Get();
int ArrowUpDown(int maxVal);
int ArrowUpDown(int p_up, int p_down, int maxVal);
int enter_esc(const std::function<int()>& funct);
};
events events::e_instance;
class deviceBase : public Printables
{
public:
const char* a_pin;
int d_pin;
String type;
String deviceName;
bool inUse;
int actualCount;
public:
String getType() override;
int getActualCount() override;
String getName() override;
String getInUse() override;
};
class senzor : public deviceBase
{
private:
int Value;
int triggValue;
public:
int p_triggValue = 10;
static int allSenzors;
friend events;
senzor();
~senzor();
public:
int getValue();
int Calibration();
void changeTriggVal(int x);
void Reset();
void nullCalibration();
void Menu(int x);
void setName(String deviceName);
void setInUse(bool x);
int getPin();
};
int senzor::allSenzors = 0;
if you have some good advice to my code writing i will be also very glad
//Class.cpp
#include <iostream>
#include <string>
#include <functional>
#define LOG(x) std::cout << x << std::endl;
#define PINMENU 12
#define PINENTER 8
#define PINESC 9
#define PINUP 11
#define PINDOWN 13
using String = std::string;
struct Printables
{
virtual String getType() = 0;
virtual int getActualCount() = 0; ;
virtual String getName() = 0;
virtual String getInUse() = 0;
};
#include "Class.h"
events& events::Get() {
return e_instance;
}
int events::ArrowUpDown(int maxVal) {
if (maxVal) {
menuValue = menuValue < maxVal ? menuValue++ : menuValue;
}
if (maxVal) {
menuValue = menuValue > 0 ? menuValue-- : menuValue;
}
return menuValue;
}
int events::enter_esc(const std::function<int()>&funct) {
if (1) {
while (!p_esc) {
auto f = funct;
}
}
return 1;
}
int events::ArrowUpDown(int p_up, int p_down, int maxVal) { return 666; }
events::events() {};
String deviceBase::getType() { return type; }
int deviceBase::getActualCount() { return actualCount; }
String deviceBase::getName() { return deviceName; }
String deviceBase::getInUse() {
String Status;
Status = inUse == 1 ? "Active" : "Deactive";
return Status;
}
senzor::senzor() : Value(0), triggValue(1) {
a_pin = "xx";
type = "[SENZOR]";
deviceName = "[UNKNOWN]";
inUse = 0;
allSenzors++;
actualCount = allSenzors;
a_pin = 0;
}
senzor::~senzor() {
allSenzors = 0;
}
int senzor::getValue() {
Value = 4;
return Value;
}
int senzor::Calibration() {
triggValue = triggValue < getValue() ? getValue() : triggValue;
p_triggValue = triggValue;
return p_triggValue;
}
void senzor::changeTriggVal(int x) {
p_triggValue = x;
}
void senzor::Reset() {
p_triggValue = triggValue;
}
void senzor::nullCalibration() {
triggValue = 1;
}
void senzor::setName(String deviceName) {
this->deviceName = deviceName;
}
void senzor::setInUse(bool x) {
inUse = x;
}
int senzor::getPin() {
return 4;
}
int printsss() {
return 1;
}
////////////////////////////////this what i was writing about//////////////////////////////
void senzor::Menu(int x) {
events::Get().enter_esc([&]() { triggValue = triggValue < getValue() ? getValue() : triggValue;
p_triggValue = triggValue;
return p_triggValue; });
}
but if i use lambda in arduino with enter_esc(int (*funct)()) i get this kind of error
no matching function for call to 'events::enter_esc(senzor::Menu(int)::<lambda()>)'

Can not find symbol - method Size()

I have been getting trouble with my program and can't figure out why I am getting this error which has been bugging me. Any suggestion will be of huge assistance! I don't know if i am missing something or something like that. I have correctly imported the Array Class.
private String title;
private ArrayList<Student> students;
private int courseId;
private static int courseIdList = 0;
/**
*
*/
public Course(String tile)
{
this.title = title;
courseId = courseIdList;
courseIdList++;
students = new ArrayList<Student>();
}
/**
* #param returns the title
*/
public String getTitle(String title)
{
return title;
}
/**
* #return returns the ID
*/
public int getId()
{
return courseId;
}
/**
*
*/
public void addStudent(Student students)
{
for(int i = 0; i < students.size(); i++)
{
if(students.getId() != students.get(i).getId())
{
students.add(i);
return;
}
}
}
/**
*
*/
public void removeStudent(Student students)
{
for(int i = 0; i < students.size(); i++)
{
if(students.getId() == students.get(i).getId())
{
students.remove(i);
return;
}
}
}
/**
* #return if class is above or equal to 10 then return true, else return false;
*/
public boolean isFull(Student students)
{
if(students.size() >= 30)
{
return true;
}
else
{
return false;
}
}
/**
* #returns if the class is below ten then return true, else return false
*/
public boolean cancel(Student students)
{
if( students.size() < 10)
{
return true;
}
else
{
return false;
}
}
/**
*
*/
public ArrayList<Student> getStudents()
{
return students;
}
/**
*
*/
public boolean inClass(Student students)
{
for(int i = 0; i < students.size(); i++)
{
if(student.getId() == students.get(i).getId())
{
return true;
}
}
return false;
}
/**
* boolean returns true if a student's ID mathes and false if their ID does not.
*/
public boolean equals(Student s)
{
if(this.getId() == s.getId())
{
return true;
}
return false;
}
/**
*
*/
public double getAverage()
{
double sum = 0;
for(Student s : students)
{
sum += s.getGrade();
}
double avg = sum / students.size();
return avg;
}
/**
*
*/
public void getHighestGrade()
{
int highestGrade = 0;
for(Student s : students)
{
if(students.getGrade() > s.get(i).getGrade())
{
students.highestGrade(i);
}
}
return new Student(" ", 0,0);
}
/**
*
*/
public ArrayList<Student> getWarnings()
{
for(i = 0; i < students.size; i++)
{
if (students.getGrade() <= 70)
{
return students;
}
}
}
/**
*
*/
public void removeSeniors(Student students)
{
for(i = 0; i < students.size; i++)
{
if(students.getId() == students.get(i).subString(0,2).equalsTo(17))
{
students.remove(i);
}
}
}
/**
*
*/
public void sortByGrade()
{
}
/**
*
*/
public void sortByAlpha()
{
}
/**
*
*/
public String toString()
{
String printOut = "";
printOut += "Course name: " + title + "\nStudent ID: " + courseId;
return printOut;
for(Student students : students)
{
printOut += students.toString() + "\n";
}
}
}
Now its the opposite :) students is a List and not a Student. You need to loop over the list and process each student.
public void doSomething(List<Student> students) {
// does not work because students is a List of students not a student.
students.getId(); // ERROR
// loop over the list and then get the id of a single student
for(Student student : students) {
int id = student.getId();
// do something with the id
}
}
size() is a method of the List interface
getId() is a method of your Student class.

How is it possible to randomly remove an element from vector< vector<short> >?

Below is a Sudoku initializer, I am attempting to create a function that based on User input, erases a random element from the the board. The random element can be removed from any part of the board.
class cell{
bool m_occu; //occupied is shown '.'
int m_num;
public:
cell() : m_occu(false), m_num(0) {}
void setMark(const int num){m_num = num; m_occu = true;}
bool isMarked() const { return m_occu; }
int getNum(){ return m_num;}
friend ostream& operator << (ostream& o, const cell& c){
if (!c.m_occu) return o << setw(2) << '-';
return o << setw(2) << c.m_num;
}
};
class board {
vector<vector <cell> >m_map;
bool col_row;
public:
board() {
vector<cell> a_row(9);
col_row = false;
for (int i = 0; i < 9; ++i)
{
for(int j = 0; j < 9; j++)
{
a_row[j].setMark(j+1);
}
random_shuffle(a_row.begin(), a_row.end());
m_map.push_back(a_row);
}
}
void erase(){
}
Here is the code for erase function:
void erase(std::vector your_vector){
your_vector.erase(your_vector.begin() + random(1,your_vector.size()));
}
and this the code for random number generation:
int random(int min, int max) //range(min, max)
{
bool first = true;
if ( first )
{
srand(time(NULL)); //seeding only for the first time
first = false;
}
return min + rand() % (max - min);
}

Minecraft forge: event when block is generated

Is there an event in 1.7.10 for when a block is generated, so i can place something above it. Or do i have to do that within the generation?
I already have looked online but i could not find an
onBlockGenerated
event or something like that.
You need to extend WorldGenerator
class Foo extends WorldGenerator {
protected Block[] GetValidSpawnBlocks() {
return new Block[] { Blocks.quartz };
}
public boolean generate(final World world, final Random rand, final int x, final int y, final int z) {
world.setBlock(x,y+1,z,FooModBlocks.yourFancyBlock,0,2);
}
}
And register it in your iworldgenerator
public class MagicCookieWorldGen implements IWorldGenerator {
private Foo myGenerator;
public MagicCookieWorldGen() {
super();
myGenerator = new Foo();
}
#Override
public void generate(Random random, int chunkX, int chunkZ, World world,
IChunkProvider chunkGenerator, IChunkProvider chunkProvider) {
this.worldGeneration(random, chunkX, chunkZ, world, true);
}
public void worldGeneration(final Random random, final int chunkX, final int chunkZ, final World world, final boolean newGen) {
switch (world.provider.dimensionId) {
case -1: {
this.generateNether(world, random, chunkX, chunkZ, newGen);
break;
}
case 1: {
break;
}
default: {
break;
}
}
}
private void generateNether(final World world, final Random random, final int chunkX, final int chunkZ, final boolean newGen) {
int startX = chunkX * 16;
int startZ = chunkZ * 16;
int startY = 5;
int endX = startX + 16;
int endZ = startZ + 16;
int endY = 65;
for(int x=startX;x<endX;x++)for(int z=startZ;z<endZ;z++)for(int y = startY;y<endY;y++) {
Block block = world.getBlock(x,y,z);
for(Block match : Foo.GetValidSpawnBlocks()) {
if(match == block) {
Foo.generate(world, final Random random, x, y, z);
break;
}
}
}
}
}
Then in your commonproxy in the init phase
GameRegistry.registerWorldGenerator((IWorldGenerator)(StuffLoader.worldGenerator = new MagicCookieWorldGen()), 0);
MagicCookie.log.info("Registered worldgenerator" + StuffLoader.worldGenerator);

Saving local variables - Java

Here is a program that is supposed to find out whether a sequence of numbers match the mathematical formula a[n+1] = a[n]*b+c for any combination of b and c in the integer range -9:9.
import java.util.Scanner;
public class Nastaord{
private static int[] lasTal(){
int[] tallista; //Det vi ska ha talföljden i
int i = 0; //räknare för tallista
while(true){
System.out.print("Ange tal, eller tryck enter om du är klar: ");
int nytt_tal = scanner.nextLine();
if(nytt_tal == ""){
return tallista;}
tallista[i] = nytt_tal;
i++;
}
}
private static boolean bcFinns(int[] tallista){
boolean OK = true;
for(int b = -9; b <= 9; b++){
for(int c = -9; c <= 9; c++){
for(int i = tallista.length; i > 0;i--){
OK = tallista[i] == tallista[i-1]*b+c;
if(OK == false){
break;}
}
if(OK == true){
public int b = b;
public int c = c;
return true;}
}
}
return false;
}
public static void main(String[] args){
boolean OK = bcFinns(lasTal());
if (OK == true){
System.out.print(tallista[tallista.length-1]*b+c);
}
if (OK == false){
System.out.print("No");
}
}
}
The program, on a principal level, works. The only thing is that I do not know how to save the correct numbers b and c for the sequence once they are found. I tried creating two public variables so that I can access them in the main method, but I get the following error:
Nastaord.java:30: error: illegal start of expression
public int b = b;
^
Nastaord.java:31: error: illegal start of expression
public int c = c;
Could you help me save these variables b and c in some way?
public class Nastaord{
public static int bFinal,cFinal;
Then later on:
bFinal = b;
cFinal = c;