2011-12-21 2 views
1

Существует иерархия вопросов и ответов:Хороший дизайн OOP

class Answer 
{ 
    int doubtLevel; 
} 
class YesNoAnswer extends Answer 
{ 
    boolean isYes; 
} 
class ColorAnswer extends Answer 
{ 
    int red; 
    int green; 
    int blue; 
} 

class Question 
{ 
    Context ctx; 
    abstract List<? extends Answer> answers; 
} 
class DoesItWorkQuestion extends Question 
{ 
    Thing it; 
    List<YesNoAnswer> answers; 
} 
class IsItTastyQuestion extends Question 
{ 
    Dish dish; 
    List<YesNoAnswer> answers; 
} 
class FavoriteColorQuestion extends Question 
{ 
    List<ColorAnswer> answers; 
} 

Прежде всего, я не хотел бы включить список ответов в каждом конкретном классе просто исправить тип A Ответ в. Есть ли способ определить структуру для хранения списка ответов вне вопросов? Но тип ответа должен быть исправлен для вопроса.

Затем мне нужно создать структуры, которые будут хранить значение для каждого ответа в вопросе, например. Предположим, я хочу есть калькулятор, который вычисляет вероятности для каждого ответа:

class AnswerProbability<Q extends Question> 
{ 
    Q question; 
//?? 
    double getProbability(???Answer answer){...} 
} 
class ProbabilityCalculator 
{ 
    // different params may produce different answer lists 
    //(e.g. if probability of an answer is less than 1%, don't include 
    //the answer in the list). 
    AnswerProbability<IsItTastyQuestion> tastyQuestionProbability(String param1, String param2); 
    AnswerProbability<FavoriteColorQuestion> favoriteColorQuestion(String param); 
... 
} 
... 

и как его можно использовать:

AnswerProbability<IsItTastyQuestion> prob = calculator.tastyQuestionProbability(...); 
// I want the "get" method take only YesNoAnswer type. 
println(prob.get(new YesNoAnswer(true, 10) + prob.get(new YesNoAnswer(false, 5)); 
// or: 
for(YesNoAnswer ans : prob.question.answers) 
{ 
    if(ans.isYes) 
    println(prob.get(ans)); 
} 
// Also I need work with superclasses 
List<AnswerProbability> aps; 
aps.add(calculator.calculateTastyQuestionProbability("soup", "mushroom")); 
aps.add(calculator.calculateFavoriteColorQuestion("socks")); 
.. 
// use `doubtLevel` from the `Answer` superclass. 
for(AnswerProbability ap : aps) 
{ 
    for(Answer a : ap.question.answers) 
    { 
    if(a.doubtLevel < 5) 
     println(ap.get(a)); 
    } 
} 

Итак, я хочу, чтобы избежать преобразования типов и во время выполнения проверки.

ответ

1

У вас не может быть абстрактного поля. Здесь вы можете использовать дженерики вместо этого

class Question<A extends Answers> { 
    Context ctx; 
    final List<A> answers = new ArrayList<A>(); 
} 

class DoesItWorkQuestion extends Question<YesNoAnswer> { 
    Thing it; 
} 

class FavoriteColorQuestion extends Question<ColorAnswer> { 
} 

Однако я подозреваю, что было бы более полезно записывать количество ответов.

class Question<A extends Answers> { 
    Context ctx; 
    final Map<A, Integer> answerCounts = new HashMap<>(); 
} 

class DoesItWorkQuestion extends Question<YesNoAnswer> { 
    Thing it; 
} 

class FavoriteColorQuestion extends Question<ColorAnswer> { 
} 

// later 
for(Entry<YesNoAnswer, Integer> ansCount : prob.question.answers.entrySet()) { 
    switch(ansCount.getKey()) { 
     case YES: 
      int count = ansCount.getValue(); 
      // something 
      break; 
    } 
} 

Это более эффективно, так как размер пропорционален числу возможных ответов, а не количество ответов и вычисления вероятности довольно легко.

+0

Если я использую параметр типа 'A',' AnswerProbability' (и некоторые другие классы, которые я здесь не упоминал) также должен быть _poisoned_ по этому параметру (см. Http://stackoverflow.com/questions/8416664/eliminate -типа-параметр-на-Java-генериков). Я не могу использовать «Map », потому что мне нужны разные структуры, например. вместо «Integer» я мог бы «enum Popularity» или «Double chance» и т. д. Я попытался сделать этот тип еще одним параметром, но пришел к тому, что 'DoesItWorkQuestion ' и' DoesItWorkQuestion 'имеют несовместимые типы. – kan

Смежные вопросы