Форум программистов
 
Расширенный поиск
Контакты: о проблемах с регистрацией, почтой и по другим вопросам пишите сюда - alarforum@yandex.ru, проверяйте папку спам! Обязательно пройдите активизацию e-mail.

Вернуться   Форум программистов > Delphi > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail



Ответ
 
Опции темы
Старый 17.01.2017, 21:04   #1
Janger
Форумчанин
 
Регистрация: 28.09.2011
Адрес: Москва
Сообщений: 250
Репутация: -1

icq: 445997544
Смущение Запутался в классах, подскажите

Ситуация в следующем.
Я хотел посмотреть, действительно ли работа с классами упрощает жизнь, или нет.
Представил себе что нужно создать класс, который хранит в себе целый тест. С несколькими вопросами, и вариантами к нету.
В общем, я сделал следующее.
1) Объявил классы:
Код:

  Test_Question_Variant = class
    Num : integer;
    Text: string;
    Yes : Boolean;

    procedure AddVarian(MyNum: integer; MyText: string; MyYes: Boolean);
    constructor Create;
  end;

  Test_Question = class
    Num: Integer;
    Text: string;
    Question_Variants: array of Test_Question_Variant;

    procedure AddQuestion(MyNum: integer; MyText: string; MyQuestion_Variants: Test_Question_Variant);
    constructor Create;
  end;

  Test = class
    Text: string;
    Questions: array of Test_Question;

    procedure AddTest(MyText: string; MyQuestions: Test_Question);
    constructor Create;
  end;

2) Описал все функции и конструкторы, которые к этим классам относились, примерно так вот:
Код:

{ Test_Question_Variant }

procedure Test_Question_Variant.AddVarian(MyNum: integer; MyText: string;
  MyYes: Boolean);
begin
  Num  := MyNum;
  Text := MyText;
  Yes  := MyYes;
end;

constructor Test_Question_Variant.Create;
begin
  Num := 0;
  Text:= '';
  Yes := false;
end;

{ Test_Question }

procedure Test_Question.AddQuestion(MyNum: integer; MyText: string;
  MyQuestion_Variants: Test_Question_Variant);
begin
  Num  := MyNum;
  Text := MyText;

  SetLength(Question_Variants,Length(Question_Variants)+1);
  Question_Variants[High(Question_Variants)] := MyQuestion_Variants;
end;

constructor Test_Question.Create;
begin
    Num:=0;
    Text:='';
    Question_Variants:=nil;
end;

{ Test }

procedure Test.AddTest(MyText: string; MyQuestions: Test_Question);
begin
  Text := MyText;

  SetLength(Questions,Length(Questions)+1);
  Questions[High(Questions)] := MyQuestions;
end;

constructor Test.Create;
begin
    Text:='';
    Questions:=nil;
end;

===================================
3) Пытаюсь заполнить ....
Код:

procedure TForm1.Button1Click(Sender: TObject);
var
  NVar: Test_Question_Variant;
  NQue: Test_Question;
  NTes: Test;
begin
  // Шаг 1.
  NVar := Test_Question_Variant.Create;
  NVar.Num := 1;
  NVar.Text := 'Это 1-ый вариант ответа';
  NVar.Yes := False;

  // Шаг  2.
  NQue := Test_Question.Create;
  NQue.AddQuestion(1,'Это первый вопрос',NVar);

  // Шаг 3.
  NTes := Test.Create;
  NTes.AddTest('А это имя теста',NQue);
end;

============================
Но у меня вопросы.
Правильно ли я всё объявил? (Если нет, то подскажите как правильно ..)
Далее, очень мне интересно, как же добавлять следующие вопросы в мой тест? таким же образом? (я имею в виду, можно через цикл)
и самый пожалуй важный вопрос, как читать данные из моего класса (хотя я вот пока писал, у меня появилось подозрение, что мне надо написать функцию, которая будет к примеру по номеру вопроса, находить его, а по второму номеру находить вариант ответа к найденному вопросу. К примеру вот так вот: Fuction(NumQuestion, NumVariant: integer): string)
============================
Подскажите, пожалуйста ...
Janger вне форума   Ответить с цитированием
Старый 17.01.2017, 21:26   #2
Alex11223
Модератор
Заслуженный модератор
 
Регистрация: 12.01.2011
Сообщений: 15,154
Репутация: 2960

icq: 512-7шесть5
skype: alexp.frl
По умолчанию

А заполнение точно работает? (я не вкурсе как SetLength работает)

Лучше использовать что-то типа TObjectList (generic если Дельфи 2009+).

И не делать AddTest в классе Test и т.п., лучше как-то так:
Код:

class Test
private:
    FQuestions: list...
public:
    AddQuestion(...)
    ...

class Question
private:
    FText: string;
    FAnswers: list...
public:
    AddAnswer(...)
    ...

class Answer
private:
    FIsCorrect: boolean;
    FText: string;
public:
    ...


Цитата:
Сообщение от Janger Посмотреть сообщение
как читать данные из моего класса
По-разному, зависит от задачи.
Вероятно стоит обратить внимание на property.

Ну и по-возможности обычно имеет смысл делать так, чтобы все что можно было "readonly" (неизменяемые значения после создания экземпляра, например property только с read, значения задавать в конструкторе), и все что можно было private.

Последний раз редактировалось Alex11223; 17.01.2017 в 21:58.
Alex11223 на форуме   Ответить с цитированием
Старый 17.01.2017, 22:09   #3
Janger
Форумчанин
 
Регистрация: 28.09.2011
Адрес: Москва
Сообщений: 250
Репутация: -1

icq: 445997544
По умолчанию

Цитата:
Сообщение от Alex11223 Посмотреть сообщение
А заполнение точно работает? (я не вкурсе как SetLength работает)
Ну, я недавно, достаточно часто работал с динамическими массивами, и там всё работало. думал сделать по такому же принципу.

Цитата:
Сообщение от Alex11223 Посмотреть сообщение
Лучше использовать что-то типа TObjectList (generic если Дельфи 2009+).
Мне всё же привычнее с массивами работать... Но я посмотрю Ваш метод, возможно он удобнее. Ну к примеру, с точки зрения поиска нужной строки.

Цитата:
Сообщение от Alex11223 Посмотреть сообщение
И не делать AddTest в классе Test и т.п., лучше как-то так:
Да, это более логичнее выглядит чем у меня. Спасибо за подсказку.

=================================== ==============

Я вот пока действительно, не могу придумать, как вывести данные из класса ....
Сделал вот такую штуку:

Вот так я заполняю тест
Код:

procedure TForm1.Button1Click(Sender: TObject);
var
  NVar: Test_Question_Variant;
  NQue: Test_Question;
  NTes: Test;
  i,j: integer;
begin
  for j:=1 to 5 do
  begin
    for i:=1 to 10 do
    begin
      NVar := Test_Question_Variant.Create;
      NVar.Num := i;
      NVar.Text := 'Вариант ответа №'+IntToStr(i);
      if i=5 then NVar.Yes := True else NVar.Yes := False;
    end;

    NQue := Test_Question.Create;
    NQue.AddQuestion(1,'Вопрос №'+IntToStr(j),NVar);
  end;

  NTes := Test.Create;
  NTes.AddTest('Один тест всего то ....',NQue);
end;

Добавил функцию в класс --> Test_Question_Variant = class
Код:

function Test_Question_Variant.Why(NumQuestion: integer): string;
var
  t: Test_Question;
  r: Test_Question_Variant;
  i,k: Integer;
begin
  t := Test_Question.create;
  r := Test_Question_Variant.Create;
  k:=0;
  if NumQuestion<=Length(t.Question_Variants) then
  begin
    for i:= Low(t.Question_Variants) to High(t.Question_Variants) do
    begin
      if k=NumQuestion then
      begin
        r := t.Question_Variants[i];
        Break;
      end
      else k:=k+1;
    end;

    Result := 'Наименование - '+r.Text+#13#10+
                 'Номерок- '+IntToStr(r.Num)+#13#10+
                 'Статус - '+BoolToStr(r.yes);
  end
  else
  Result := 'Произошла ошибка ... ----> '+IntToStr(Length(t.Question_Variants));
end;

Ну и соответсвенно, я решил, после всего этого безобразия, воспользоваться моей функцией, и вывести результат в Memo, я это сделал вот так вот:
Код:

procedure TForm1.Button2Click(Sender: TObject);
var
  NTes: Test_Question_Variant;
begin
  NTes := Test_Question_Variant.Create;

  Memo1.Text := NTes.Why(2);
end;

===============================
Ну и соответственно, МЕМО мне выдало сообщение: (Какие-то проблемы ... ----> 0)
===============================
Janger вне форума   Ответить с цитированием
Старый 17.01.2017, 22:28   #4
Alex11223
Модератор
Заслуженный модератор
 
Регистрация: 12.01.2011
Сообщений: 15,154
Репутация: 2960

icq: 512-7шесть5
skype: alexp.frl
По умолчанию

Что вы сделать пытаетесь? Что за цикл?

"Вопрос №" и т.п. лучше не записывать сразу в строку, только при выводе.
Добавить для номера поле если надо (но может проще обойтись порядком в массивах? И вопросы/ответы ж бывает перемешивают, чтоб были всегда разные/разный порядок)

Цитата:
Сообщение от Janger Посмотреть сообщение
Я хотел посмотреть, действительно ли работа с классами упрощает жизнь, или нет.
Если правильно использовать, то да.

Вообще если выбирать из вещей, которые упрощают жизнь и дают возможность спать ночью, то одна из самых важных — это автоматические тесты (юнит тесты и т.д.).
И система контроля версий (git).

Последний раз редактировалось Alex11223; 17.01.2017 в 22:52.
Alex11223 на форуме   Ответить с цитированием
Старый 18.01.2017, 08:38   #5
Janger
Форумчанин
 
Регистрация: 28.09.2011
Адрес: Москва
Сообщений: 250
Репутация: -1

icq: 445997544
По умолчанию

да всё просто.
я циклом заполняю массив в классе,
и потом хочу просто получить данные, из массива
Janger вне форума   Ответить с цитированием
Старый 18.01.2017, 09:59   #6
Alex11223
Модератор
Заслуженный модератор
 
Регистрация: 12.01.2011
Сообщений: 15,154
Репутация: 2960

icq: 512-7шесть5
skype: alexp.frl
По умолчанию

Я про второй цикл, в функции со странным названием Why.

Если вы там пытаетесь получить ответ с указанным номером, то говорю ж, проще было бы использовать порядок в массиве (или что-то типа Dictionary/Map, но стандартный TDictionary завезли тоже только с 2009).

Но вы там что-то странное делаете потому что вы создали новые (пустые) экземпляры вопроса и ответа.
Alex11223 на форуме   Ответить с цитированием
Старый 18.01.2017, 11:20   #7
netpolice
Форумчанин
 
Аватар для netpolice
 
Регистрация: 14.02.2013
Сообщений: 217
Репутация: 109
По умолчанию

Меня смущает момент, что Вы в каждом обработчике (Button2Click и т.д.) объявляете экземпляр класса, вызываете конструктор, что то с ним делаете и забываете о классе. Т.е. как минимум засоряете память, ну или все время работаете с разными экземплярами. Как по мне, то всякие
Код:

var
  NTes: Test_Question_Variant;

должны быть описаны в классе TForm1... Ну или еще где нибудь более глобально...
netpolice вне форума   Ответить с цитированием
Ответ



Опции темы

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Функции в классах C++ Ligeros905 Помощь студентам 0 12.05.2014 12:51
Перемнные в классах Mariolka PHP 10 14.11.2013 01:00
var в классах RuVarez Общие вопросы Delphi 1 20.04.2012 17:12
Вопрос о классах (С++) Александр Елис Помощь студентам 5 25.01.2010 21:49
Сборка или чистая XP ? Подскажите я запутался. spamer Windows 8 16.10.2009 23:50




13:24.


Powered by vBulletin® Version 3.8.8 Beta 2
Copyright ©2000 - 2018, Jelsoft Enterprises Ltd.

купить трафик


как улучшить посещаемость, а также решения по монетизации сайтов, видео и приложений

RusProfile.ru


Справочник российских юридических лиц и организаций.
Проекты отопления, пеллетные котлы, бойлеры, радиаторы
интернет магазин respective.ru