2016-09-11 2 views
4

СИТУАЦИИDelphi запись помощник для двойной

Я написал класс для второго уравнений степени, которая выглядит примерно так. Вы можете найти here полный код класса, но это не очень актуально для вопроса.

type 
TArrayOfDouble = array of array of double; 

type 
TEqSecGrado = class 
    private 
    //variables 
    a, b, c: double; 
    delta: double; 
    solutions: TArrayOfDouble; 
    solRealCount: integer; 
    solImaginaryCount: integer; 
    class var currentIstances: integer; 
    class var totalIstances: integer; 
    //methods 
    function getDelta(const vala, valb, valc: double): double; overload; 
    public 
    constructor Create(const a, b, c: double); 
    destructor Destroy; override; 
    //methods 
    function getDelta: double; overload; 
    function getSolutions: TArrayOfDouble; virtual; 
    //properties 
    property valueOfA: double read a; 
    property valueOfB: double read b; 
    property valueOfC: double read c; 
    property realSolutionsCount: integer read solRealCount; 
    property imaginarySolutionsCount: integer read solImaginaryCount; 
    class property currentEquationsCount: integer read currentIstances; 
    class property totalEquationsCount: integer read totalIstances; 
end; 

Я думал, чтобы создать новый тип, называемый TArrayOfDouble, который будет содержать решение моего уравнения. В главной форме я использую класс таким образом:

procedure TForm3.Button1Click(Sender: TObject); 
var solver: TEqSecGrado; 
    soluzioni: TArrayOfDouble; 
begin 

//f(x) = 3x^2 - x - 2 -> [sol.1 = 1 | sol.2 = -0,666666666666667] 
solver := TEqSecGrado.Create(3,-1,-2); 

try 
    soluzioni := solver.getSolutions; 
    //soluzioni[0][0] = 1; soluzioni[0][1] = 0; 
    //soluzioni[1][0] = -0,666666666666667; soluzioni[1][1] = 0; 
finally 
    solver.Free; 
end; 

end; 

Теперь у меня есть результаты внутри soluzioni и я могу выводить их. (Я использовал матрицу, потому что в первом месте я помещал реальные решения, в этом случае 1 и -0.67, а также во втором спортивном немастическом решении, если это необходимо).


ВОПРОС

Когда я выводить решения, которые я хочу, чтобы преобразовать их в виде дроби. Я хотел сделать что-то вроде soluzioni[a][b].toFraction. Поэтому я подумал, что могу использовать помощник записи для двойника.

type 
TSupport = record helper for Double 
    function toFraction: string; 
    function toString: string; //I have added this LATER 
end; 

Здесь я прихожу со своими сомнениями. Как только я создал метод TSupport и toFraction, мне удалось вызвать soluzioni [0] [0] .toFraction, но я не мог назвать soluzioni [i] [0] .toString.

Чтобы решить мою проблему, я решил добавить функцию toString, и все сработало. Помогает ли помощник записи скрывать все другие методы? Если бы я удалил помощник записи вместо этого, я могу использовать снова метод toString, как всегда.

Я знаю, что помощники - это способ расширить класс без использования наследования, но почему я могу использовать только методы, которые я объявил в моем помощнике?

+0

Как реализовать значимую функцию, которая преобразует произвольное значение с плавающей запятой в дробь. Если вы хотите сделать это именно тогда, вы всегда получите долю формы k/2^n, где k и n - целые числа. Это то, что вы действительно хотите? –

+0

Я делаю это для своего экзамена по математике в университете, и мне предложили использовать непрерывные фракции. Я даю лишь приблизительный результат. Например, sqrt (3)/3 будет преобразован во фракцию, но, конечно, эти 2 значения не совпадают, а доля просто огромная аппроксимация –

+0

Кроме того, ваше значение 'double' на самом деле не будет равно' sqrt (3)/3', потому что это значение не представляется в виде двоичного значения с плавающей запятой –

ответ

7

Ограничение помощников класса и записей состоит в том, что только один может быть активным одновременно. Метод ToStringDouble фактически реализован в помощнике записи, предоставленном Delphi RTL. Когда вы присоедините своего помощника к типу, тогда помощник RTL больше не будет активен.

documentation говорит:

Вы можете определить и связать несколько помощников с одного типа. Однако только нулевой или один помощник применяется в любом конкретном месте в исходном коде. Будет применен помощник, определенный в ближайшей области. Класс или вспомогательная область записи определяются в обычном режиме Delphi (например, справа налево в предложении использования устройства).

Это давняя проблема, о которой Embarcadero знает о том, что с тех пор появились помощники. За многие долгие годы они не рассматривали этот вопрос и с лучшей волей в мире, я думаю, вы должны предположить, что они никогда не будут.

Итак, у вас есть два варианта:

  1. Attach свой собственный помощник, и принять, что функциональность помощника RTL не будут доступны для вас.
  2. Внесите свою функциональность не с помощью помощника.
+0

Хорошо, это произошло потому, что компилятор игнорирует помощника RTL и заботится только о последнем реализованном помощнике (в данном случае, мой) –

+1

Исправить. Я добавил ссылку doc и соответствующий отрывок –

+3

Как и FYI: вы можете одновременно использовать несколько помощников CLASS. Помощники CLASS поддерживают наследование, поэтому вы можете фактически определить свой помощник класса как расширение предыдущего, как в _TStringsHelper = CLASS HELPER (VclHelpers.TStringsHelper) для TStrings_, и как VclHelpers.TStringsHelper, так и ваш только что объявленный TStringsHelper из текущего UNIT будет быть доступным. К сожалению, помощники RECORD не поддерживают наследование, поэтому единственный способ, которым я нашел «расширение» существующего помощника RECORD, заключается в повторной реализации помощника как метода INLINE, который вызывает старый. – HeartWare

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