Тест программирования Java для интервью
Вот тест программирования, используемый в собеседовании. Я нахожу, что у него очень странная перспектива, отличная от OO, и удивляйтесь, почему кто-то подходит к конструктору с этой точки зрения. Будучи очень опытным программистом на Java, я сразу же сомневаюсь в способности человека, написавшего этот код и странную перспективу вопроса.
Я нахожу эти странные из контекстных вопросов на собеседование тревожными. Мне бы хотелось получить отзывы от других опытных программистов Java OO.
Завершите конструктор Solver, чтобы вызов solveAll возвращал список с двумя значениями включая квадратный корень и обратный целому числу, переданному как параметр.
public interface MathFunction {
double calculate(double x);
}
public class Solver {
private List<MathFunction> functionList;
public Solver() {
//Complete here
}
public List<Double> solveAll(double x) {
List<Double> result = new ArrayList<Double>();
for (MathFunction function : this.functionList) {
result.add(new Double(function.calculate(x)));
}
return result;
}
}
Ответы
Ответ 1
Это тестирование ваших шаблонов проектирования, используя простейший возможный метод. Я думаю, что это может быть Стратегия (или некоторые другие поведенческие модели). Смотрите следующее:
http://en.wikipedia.org/wiki/Strategy_pattern
http://en.wikipedia.org/wiki/Behavioral_pattern
Если вы собираетесь провести собеседование по Java, вы должны иметь возможность идентифицировать шаблон дизайна, на который они намекают, и это должно помешать вам быть слишком нерешенным!
Чтобы ответить на вопрос, создайте два класса, которые реализуют MathFunction
по мере необходимости, затем создайте два экземпляра и сохраните их в functionList
.
Дело здесь не в том, что "вы можете делать вычисления этим странным образом", это "вы можете определить шаблоны дизайна".
Ответ 2
Я согласен, что это запутывает и перерабатывает.
Но я действительно думаю, что код достаточно объектно-ориентированный. Это пример стратегии. Код, который генерирует список ответов, не волнует, как вычисляются ответы - две проблемы разделены, и может быть применена другая стратегия расчета без необходимости касаться кода, который генерирует список.
Чтобы сделать класс более полезным, эти функции должны передаваться извне (например, инъекции зависимостей), а не создаваться в конструкторе.
Вы знаете ответ, я полагаю, но для чего это стоит...
public Solver() {
functionList = new ArrayList<MathFunction>();
functionList.add(new MathFunction() {
@Override
public double calculate(double x) {
return 1d/x;
}
});
functionList.add(new MathFunction() {
@Override
public double calculate(double x) {
return Math.sqrt(x);
}
});
}
Ответ 3
ИМХО, это действительно странный подход. Имя Solver
является общим, оно не должно выполнять определенные операции по умолчанию. Однако, может быть, это было частью интервью? Часть первая: просто выполните запрос. Часть вторая: скажите, что это странно.
Я бы сказал, что гораздо лучше использовать метод addMathFunction(MathFunction mf)
. И если хотите, создать подклассы, расширяющие класс Solver
и добавление MathFunctions в их конструктор.
Ответ 4
Хотя я согласен с тем, что это, вероятно, не самый лучший способ или самый способ OO для этого, я должен был предположить, что суть этого упражнения - понять, насколько хорошо вы понимаете Inheritance, Interfaces и, возможно, анонимные внутренние классы, Это единственное, что я могу понять.
Ответ 5
Я думаю, они хотели, чтобы вы добавили два элемента в список функций. Каждый из них будет реализовывать интерфейс MathFunction, один для квадратного корня и один для обратного.
Прбоблем находится в деталях:
1- У вас есть функция, которая возвращает 2 значения, потому что она выполняет две разные вещи: плохую
2- Если вы хотите иметь этот класс "все-все", m было бы интересно получить Mathfunctions в качестве параметра, чтобы вы могли делать любые типы MathFunctions, MathFunctions были бы параметризуемыми
Ответ 6
Вот мое решение. Это простая иллюстрация factory class.
public Solver() {
functionList = new ArrayList<MathFunction>();
MathFunction sqrt = new MathFunction() {
@Override
public double calculate(double x) {
return Math.sqrt(x);
}
};
functionList.add(sqrt);
MathFunction inverse = new MathFunction() {
@Override
public double calculate(double x) {
return 1.0D / x;
}
};
functionList.add(inverse);
}
Этот вопрос показывает две вещи:
- Независимо от того, понимает ли программист математические термины, такие как обратные.
- Знает ли программист, что экземпляры интерфейсов или классов могут быть сохранены в списке и повторены позже.
Ответ 7
Хорошо, я закодировал решение своего вопроса. Мой инстинкт, что ничто не должно быть в конструкторе, кажется правильным. ФункцияList не является статической, поэтому для ее инициализации нужен экземпляр. Он задает целое число, поэтому я округлю до целого. Обратная функция не является продвинутой математикой.
import java.util.ArrayList;
import java.util.List;
import java.lang.Math;
public class Solver {
private List<MathFunction> functionList = new ArrayList<MathFunction>();;
public Solver() {
// Complete here
}
public void initFunctionList() {
MathFunction functionSquareRoot = new MathFunction(){
@Override
public double calculate(double x) {
return (x<0 ? 0: Math.sqrt(x)); // maybe we need throw an exception here for negative numbers, but we'll just set it to 0
}};
MathFunction functionInverse = new MathFunction(){
@Override
public double calculate(double x) {
return (x!=0.0 ? 1/x : 0);
}
};
functionList.add(functionSquareRoot);
functionList.add(functionInverse);
}
public List<Double> solveAll(double x) {
List<Double> result = new ArrayList<Double>();
for (MathFunction function : this.functionList) {
result.add(new Double(function.calculate(x)));
}
return result;
}
}
public interface MathFunction {
double calculate(double x);
}
public class TestSolver {
/**
* @param args
*/
public static void main(String[] args) {
Solver s = new Solver();
s.initFunctionList();
System.out.println(s.solveAll(16.0));
}
}
Я заблуждаюсь, что конструктор может быть
public Solver() {
// Complete here
MathFunction functionSquareRoot = new MathFunction(){
@Override
public double calculate(double x) {
return (x<0 ? 0: Math.sqrt(x)); // maybe we need throw an exception here for negative numbers, but we'll just set it to 0
}};
MathFunction functionInverse = new MathFunction(){
@Override
public double calculate(double x) {
return (x!=0.0 ? 1/x : 0);
}
};
functionList.add(functionSquareRoot);
functionList.add(functionInverse);
}
Ответ 8
Немного надуманный, кажется мне ближе к дизайну декоратора.
Не уверен, что бы я сказал во время интервью, но вот как я его кодирую:
package math;
import java.util.ArrayList;
import java.util.List;
public class DecoratorMath
{
interface MathFunction
{
double calculate(double x);
}
public static void main(String[] args)
{
DecoratorMath decoratorMath = new DecoratorMath();
decoratorMath.go();
}
public void go()
{
Solver solver = new Solver();
decorate(solver);
List<Double> results = solver.solveAll(02);
for (Double d :results)
{
System.out.println(d);
}
}
public void decorate(Solver solver)
{
solver.addFunction(new MathFunction()
{
@Override
public double calculate(double x)
{
return Math.sqrt(x);
}
});
solver.addFunction(new MathFunction()
{
@Override
public double calculate(double x)
{
return 1d/x;
}
});
}
class Solver
{
private List<MathFunction> mathFunctions = new ArrayList<MathFunction>();
public void addFunction(MathFunction mathFunction)
{
mathFunctions.add(mathFunction);
}
public List<Double> solveAll(double x)
{
List<Double> result = new ArrayList<Double>();
for (MathFunction function : mathFunctions)
{
result.add(new Double(function.calculate(x)));
}
return result;
}
}
}
Ответ 9
Выполнение всего этого в конструкторе - это просто плохая практика. Во всяком случае, мое решение "все-в-одном".
import java.util.*;
import java.math.*;
//sqrt / inverse
public class Solver{
private List<MathFunction> functionList;
public interface MathFunction{
double calculate(double x);
}
class X implements MathFunction {
public double calculate(double x) {
return Math.sqrt(x);
}
}
class Y implements MathFunction {
public double calculate(double y) {
return 1/y;
}
}
public Solver(){
//here
functionList = new ArrayList<MathFunction>();
MathFunction f = (MathFunction) new X();
functionList.add(f);
MathFunction f2 = (MathFunction) new Y();
functionList.add(f2);
}
public List<Double> solveAll(double x){
List<Double> result=new ArrayList<Double>();
for (MathFunction function : this.functionList){
result.add(new Double(function.calculate(x)));
}
return result;
}
public static void main(String... args) {
System.out.println("result="+new Solver().solveAll(123));
}
}