Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Сохранение типа списка объектов

Delphi , Синтаксис , Типы и Переменные

Сохранение типа списка объектов



unit Dates;

interface

uses
  SysUtils, Classes;

type
  TDate = class (TComponent)
  private
    FMonth, FDay, FYear: Integer;
    FOnChange: TNotifyEvent;
  protected
    function DaysInMonth: Integer;
    procedure SetMonth (Value: Integer);
    procedure SetYear (Value: Integer);
    procedure SetDay (Value: Integer);
    procedure DoChange; virtual;
  public
    constructor Create (AOwner: TComponent); override;
    constructor Init (m, d, y: Integer);
    procedure SetValue (m, d, y: Integer);
    function LeapYear: Boolean;
    procedure Increase;
    procedure Decrease;
    procedure Add (NumberOfDays: Integer);
    procedure Subtract (NumberOfDays: Integer);
    function GetText: string;
    // properties:
    property Text: string read GetText;
  published
    property Day: Integer read FDay write SetDay;
    property Month: Integer read FMonth write SetMonth;
    property Year: Integer read FYear write SetYear;
    // event:
    property OnChange: TNotifyEvent
      read FonChange write FOnChange;
  end;

// dates exception
type
  EDateOutOfRange = class (Exception);

procedure Register;

implementation

constructor TDate.Create (AOwner: TComponent);
var
  Y, D, M: Word;
begin
  inherited Create (AOwner);
  // today...
  DecodeDate (Now, Y, M, D);
  FYear := Y;
  FMonth := M;
  FDay := D;
end;

constructor TDate.Init (m, d, y: Integer);
begin
  SetValue (m, d, y);
end;

procedure TDate.DoChange;
begin
  if Assigned (FOnChange) then
    FOnChange (self);
end;

procedure TDate.SetValue (m, d, y: Integer);
var
  OldY, OldM: Integer;
begin
  // store the old value
  OldY := FYear;
  OldM := FMonth;
  // assing the new value
  try
    FYear := y;
    // check the ranges
    SetMonth (m);
    SetDay (d);
    DoChange;
  except
    on EDateOutOfRange do
    begin
      // reset the values
      FYear := OldY;
      FMonth := OldM;
      // let the error show up
      raise;
    end;
  end;
end;

procedure TDate.SetMonth (Value: Integer);
begin
  if (Value >= 1) and (Value <= 12) then
  begin
    FMonth := Value;
    DoChange;
  end
  else
    raise EDateOutOfRange.Create ('Month out of range');
end;

procedure TDate.SetYear (Value: Integer);
begin
  FYear := Value;
  DoChange;
end;

procedure TDate.SetDay (Value: Integer);
begin
  if (Value >= 1) and (Value <= DaysInMonth) then
  begin
    FDay := Value;
    DoChange;
  end
  else
    raise EDateOutOfRange.Create ('Day out of range');
end;

function TDate.LeapYear: Boolean;
begin
  // compute leap years, considering "exceptions"
  if (FYear mod 4 <> 0) then
    LeapYear := False
  else if (FYear mod 100 <> 0) then
    LeapYear := True
  else if (FYear mod 400 <> 0) then
    LeapYear := False
  else
    LeapYear := True;
end;

function TDate.DaysInMonth: Integer;
begin
  case FMonth of
    1, 3, 5, 7, 8, 10, 12:
      DaysInMonth := 31;
    4, 6, 9, 11:
      DaysInMonth := 30;
    2:
      if (LeapYear) then
        DaysInMonth := 29
      else
        DaysInMonth := 28;
    else
      // if the month is not correct
      DaysInMonth := 0;
  end;
end;

procedure TDate.Increase;
begin
  // if this day is not the last of the month
  if FDay < DaysInMonth then
    Inc (FDay) // increase the value by 1
  else
  // if it is not in December
    if FMonth < 12 then
    begin
      // Day 1 of next month
      Inc (FMonth);
      FDay := 1;
    end
    else
    begin
      // else it is next year New Year's Day
      Inc (FYear);
      FMonth := 1;
      FDay := 1;
    end;
  DoChange;
end;

// exactly the reverse of the Increase method
procedure TDate.Decrease;
begin
  if FDay > 1 then
    Dec (FDay) // decrease the value by 1
  else
    // it is the first of a month
    if FMonth > 1 then
    begin
      // assign last day of previous month
      Dec (FMonth);
      FDay := DaysInMOnth;
    end
    else
    // it is the first of January
    begin
      // assign last day of previous year
      Dec (FYear);
      FMonth := 12;
      FDay := DaysInMOnth;
    end;
  DoChange;
end;

function TDate.GetText: string;
begin
  GetText :=  Format ('%s %d, %d',
    [LongMonthNames[Month], Day, Year]);
end;

procedure TDate.Add (NumberOfDays: Integer);
var
  N: Integer;
begin
  // increase the day n times
  for N := 1 to NumberOfDays do
    Increase;
end;

procedure TDate.Subtract (NumberOfDays: Integer);
var
  N: Integer;
begin
  // decrease the day n times
  for N := 1 to NumberOfDays do
    Decrease;
end;

procedure Register;
begin
  RegisterComponents ('Md3', [TDate]);
end;

end.


unit SList;

interface

uses
  Classes;

type
  TSafeList = class
  private
    LType: TClass;
    FList: TList;
    function Get (Index: Integer): TObject;
    procedure Put (Index: Integer; Item: TObject);
    function GetCount: Integer;
  public
    constructor Create (CType: TClass);
    destructor Destroy; override;
    function Add (Item: TObject): Integer;
    function Equals(List: TSafeList): Boolean;
    property Count: Integer read GetCount;
    property Items [Index: Integer]: TObject
      read Get write Put; default;
  end;

implementation

uses
   SysUtils;

constructor TSafeList.Create (CType: TClass);
begin
  FList := TList.Create;
  LType := CType;
end;

destructor TSafeList.Destroy;
begin
  FList.Free;
  inherited Destroy;
end;

function TSafeList.Get(Index: Integer): TObject;
begin
  Result := FList [Index];
end;

function TSafeList.Add (Item: TObject): Integer;
var
  Test: Boolean;
begin
  try
    Test := Item is LType;
  except
    on Exception do
      raise EInvalidCast.Create (Format (
        'SafeList: Cannot add a non-object to a list of %s objects',
        [LType.ClassName]));
  end;
  if Test then
    Result := FList.Add (Item)
  else
    raise EInvalidCast.Create (Format (
      'SafeList: Cannot add a %s object to a list of %s objects',
      [Item.ClassName, LType.ClassName]));
end;

procedure TSafeList.Put(Index: Integer; Item: TObject);
var
  Test: Boolean;
begin
  try
    Test := Item is LType;
  except on Exception do
    raise EInvalidCast.Create (Format (
      'SafeList: Cannot put a non-object into a list of %s objects',
      [LType.ClassName]));
  end;
  if Test then
    FList [Index] := Item
  else
    raise EInvalidCast.Create (Format (
      'SafeList: Cannot put a %s object into a list of %s objects',
      [TObject(Item).ClassName, LType.ClassName]));
end;

function TSafeList.GetCount: Integer;
begin
  Result := FList.Count;
end;

function TSafeList.Equals(List: TSafeList): Boolean;
var
  I: Integer;
begin
  Result := False;
  if List.Count <> FList.Count then
    Exit;
  for I := 0 to List.Count - 1 do
    if List[I] <> FList[I] then
      Exit;
  Result := True;
end;

end.


unit SafeForm;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, SList;

type
  TForm1 = class(TForm)
    ButtonAddDates: TButton;
    ButtonAddButton: TButton;
    ButtonAddPointer: TButton;
    ButtonNewDate: TButton;
    ListBox1: TListBox;
    ButtonNewButton: TButton;
    ButtonNewPointer: TButton;
    procedure ButtonAddDatesClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure ButtonAddButtonClick(Sender: TObject);
    procedure ButtonAddPointerClick(Sender: TObject);
    procedure ButtonNewDateClick(Sender: TObject);
    procedure ButtonNewButtonClick(Sender: TObject);
    procedure ButtonNewPointerClick(Sender: TObject);
  private
    List: TSafeList;
  public
    procedure UpdateList;
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

uses
  Dates;

procedure TForm1.ButtonAddDatesClick(Sender: TObject);
var
  I: Integer;
begin
  Randomize;
  try
    for I := 1 to 10 do
      List.Add (TDate.Init (
        1 + Random (12), 1 + Random (28),
        1900 + Random (200)));
  finally
    UpdateList;
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  List := TSafeList.Create (TDate);
end;

procedure TForm1.ButtonAddButtonClick(Sender: TObject);
begin
  List.Add (Sender);
  UpdateList;
end;

procedure TForm1.ButtonAddPointerClick(Sender: TObject);
var
  P: Pointer;
begin
  P := @Form1;
  List.Add (P);
  UpdateList;
end;

procedure TForm1.UpdateList;
var
  I: Integer;
begin
  ListBox1.Clear;
  for I := 0 to List.Count - 1 do
    Listbox1.Items.Add ((
      TDate(List [I]).GetText));
end;

procedure TForm1.ButtonNewDateClick(Sender: TObject);
begin
  List [1] := TDate.Create (self);
  UpdateList;
end;

procedure TForm1.ButtonNewButtonClick(Sender: TObject);
begin
  List [1] := Sender;
  UpdateList;
end;

procedure TForm1.ButtonNewPointerClick(Sender: TObject);
var
  S: String;
begin
  S := 'Hi';
  List [1] := Pointer(S);
  UpdateList;
end;

end.

Загрузить весь проект

Программный проект на языке Delphi, состоящий из трех модулей: Dates, SList и SafeForm. Вот подробное описание каждого модуля:

Dates.pas Этот модуль определяет класс TDate, который представляет собой дату. Класс имеет свойства для месяца, дня и года, а также методы для увеличения или уменьшения даты на один день, добавления или вычитания заданного количества дней и получения текстового представления даты. Кроме того, класс TDate выбрасывает исключения при попытке установить недопустимую дату (например, 30 февраля).

SList.pas Этот модуль определяет класс TSafeList, который является списком объектов, который может содержать только объекты определенного типа. Класс имеет методы для добавления и удаления элементов из списка, а также метод для проверки равенства двух списков. Класс TSafeList использует underlying объект TList для хранения элементов, но добавляет дополнительный слой безопасности, проверяя каждый элемент на соответствие типу перед добавлением в список.

SafeForm.pas Этот модуль определяет класс TForm1, который является формой с несколькими кнопками и списком. Форма имеет методы для обработки кликов по кнопкам и обновления списка. Класс TSafeList используется для хранения дат в списке формы. Форма может добавлять даты в список с помощью кнопки "Добавить даты" или другие типы объектов (например, кнопки или указатели) с помощью кнопок "Добавить кнопку" и "Добавить указатель". Форма также имеет методы для обновления списка при добавлении или удалении элемента из списка. В целом, этот проект демонстрирует, как создать custom список класса, который может содержать только объекты определенного типа, и использовать его в приложении Delphi.

Сохранение типа списка объектов: в этом проекте создана система для хранения и обмена данными о датах, использованы классы TDate и TSafeList. Класс TDate отвечает за хранение и форматирование дат, а класс TSafeList - за безопасное хранение списка объектов


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: Типы и Переменные ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-12-22 20:14:06
2025-06-16 10:51:07/0.0067520141601562/0