Sdílet prostřednictvím


Operátor přetížení (F#)

Toto téma popisuje přetěžování aritmetické operátory v záznamu typu nebo třídy a na globální úrovni.

// Overloading an operator as a class or record member. 
static member (operator-symbols) (parameter-list) = 
    method-body
// Overloading an operator at the global level
let [inline] (operator-symbols) parameter-list =
    function-body

Poznámky

In the previous syntax, the operator-symbol is one of +, -, *, /, =, and so on.parameter-list v pořadí, které se objevují v obvyklých syntaxi pro tento operátor určuje operandy.method-body Vytvoří výslednou hodnotu.

Operátor přetížení pro hospodářské subjekty musí být statický.Operátor přetížení pro unární operátory, například + a -, musíte použít tildou (~) v operator-symbol označuje, že provozovatel je unární operátor a binární operátor, jak ukazuje následující prohlášení.

static member (~-) (v : Vector)

Následující kód ilustruje třída vector, která má pouze dva operátory, jeden pro unární negace a jeden pro násobení skalární.V příkladu jsou potřebné pro skalární násobení dvou přetížení, protože musí pracovat bez ohledu pořadí vektorové a skalární.

type Vector(x: float, y : float) =
   member this.x = x
   member this.y = y
   static member (~-) (v : Vector) =
     Vector(-1.0 * v.x, -1.0 * v.y)
   static member (*) (v : Vector, a) =
     Vector(a * v.x, a * v.y)
   static member (*) (a, v: Vector) =
     Vector(a * v.x, a * v.y)
   override this.ToString() =
     this.x.ToString() + " " + this.y.ToString()

let v1 = Vector(1.0, 2.0)

let v2 = v1 * 2.0
let v3 = 2.0 * v1

let v4 = - v2

printfn "%s" (v1.ToString())
printfn "%s" (v2.ToString())
printfn "%s" (v3.ToString())
printfn "%s" (v4.ToString())

Vytváření nových hospodářských subjektů

Standardní operátory může přetížit, ale můžete také vytvořit nové subjekty sekvence určité znaky.Allowed operator characters are !, %, &, *, +, -, ., /, <, =, >, ?, @, ^,|, and ~.~ Znak má zvláštní význam, že Unární operátor a není součástí sekvence znaků operátor.Všechny operátory lze použít unární, je popsán v Prefix a operátory Infix dále v tomto tématu.

V závislosti na posloupnost přesné znaků, které používáte bude mít váš operátor určitých přednost a asociativita operátorů.Asociativitu můžete buď zleva doprava nebo zprava doleva a používá se při každém operátorů stejnou úroveň priority se zobrazují v pořadí, bez závorek.

Znak operátor . neovlivní prioritu, takže například pokud chcete definovat vlastní verzi násobení, který má stejnou přednost a asociativita operátorů jako obyčejný násobení, můžete vytvořit operátory jako .*.

Tabulka, která zobrazuje přednost všech operátorů v F# lze nalézt v Referenční operátor (F#) a symbol.

Názvy přetížených operátor

Kompilátor F# kompiluje výraz operátor, vygeneruje metodu, která má název generovaný kompilátorem pro tento operátor.Toto je název, který se objeví v dílčí jazyk Microsoft (MSIL) pro metodu a také odraz a technologie IntelliSense.Obvykle není potřeba používat tyto názvy v F# kódu.

Následující tabulka zobrazuje standardní operátory a jejich odpovídající generovány názvy.

Operátor

Vygenerovaný název

[]

op_Nil

::

op_Cons

+

op_Addition

-

op_Subtraction

*

op_Multiply

/

op_Division

@

op_Append

^

op_Concatenate

%

op_Modulus

&&&

op_BitwiseAnd

|||

op_BitwiseOr

^^^

op_ExclusiveOr

<<<

op_LeftShift

~~~

op_LogicalNot

>>>

op_RightShift

~+

op_UnaryPlus

~-

op_UnaryNegation

=

op_Equality

<=

op_LessThanOrEqual

>=

op_GreaterThanOrEqual

<

op_LessThan

>

op_GreaterThan

?

op_Dynamic

?<-

op_DynamicAssignment

|>

op_PipeRight

<|

op_PipeLeft

!

op_Dereference

>>

op_ComposeRight

<<

op_ComposeLeft

<@ @>

op_Quotation

<@@ @@>

op_QuotationUntyped

+=

op_AdditionAssignment

-=

op_SubtractionAssignment

*=

op_MultiplyAssignment

/=

op_DivisionAssignment

..

op_Range

.. ..

op_RangeStep

Operátor znaků, které zde nejsou uvedeny jiné kombinace lze použít jako operátory a názvy, které jsou vytvořeny prostřednictvím názvů pro jednotlivé znaky z následující tabulky.Například +!becomes op_PlusBang.

Operátor znak

Název

>

Greater

<

Less

+

Plus

-

Minus

*

Multiply

/

Divide

=

Equals

~

Twiddle

%

Percent

.

Dot

&

Amp

|

Bar

@

At

^

Hat

!

Bang

?

Qmark

(

LParen

,

Comma

)

RParen

[

LBrack

]

RBrack

Předpony a zaváděcí operátory

Předpona operátory se očekává se umístí před operand nebo operandy, podobně jako funkce.Infix operátory se očekává umístit mezi dva operandy.

Jako předponové operátory lze použít pouze u některých operátorů.Některé operátory jsou vždy předponové operátory, jiné mohou být zaváděcí nebo předponu a zbývající jsou vždy infix operátory.Hospodářské subjekty, které začínají !, s výjimkou !=a operátor ~, nebo opakované sekvence~, jsou vždy předponové operátory.The operators +, -, +., -., &, &&, %, and %% can be prefix operators or infix operators.Rozlišit předponu verzi těchto operátorů z verze zaváděcí přidáním ~ na začátku předponu operátor, když je definována.~ Nebude použito, pokud použijete operátor, pouze pokud je definována.

Příklad

Následující kód ilustruje použití operátoru přetížení implementovat typ zlomku.Zlomek je zastoupena čitatel a jmenovatel.Funkce hcf slouží k určení koeficientu společného nejvyšší, který je použit pro snížení zlomky.

// Determine the highest common factor between
// two positive integers, a helper for reducing
// fractions.
let rec hcf a b =
  if a = 0u then b
  elif a<b then hcf a (b - a)
  else hcf (a - b) b

// type Fraction: represents a positive fraction
// (positive rational number).
type Fraction =
   {
      // n: Numerator of fraction.
      n : uint32
      // d: Denominator of fraction.
      d : uint32
   }

   // Produce a string representation. If the
   // denominator is "1", do not display it.
   override this.ToString() =
      if (this.d = 1u)
        then this.n.ToString()
        else this.n.ToString() + "/" + this.d.ToString()

   // Add two fractions.
   static member (+) (f1 : Fraction, f2 : Fraction) =
      let nTemp = f1.n * f2.d + f2.n * f1.d
      let dTemp = f1.d * f2.d
      let hcfTemp = hcf nTemp dTemp
      { n = nTemp / hcfTemp; d = dTemp / hcfTemp }

   // Adds a fraction and a positive integer.
   static member (+) (f1: Fraction, i : uint32) =
      let nTemp = f1.n + i * f1.d
      let dTemp = f1.d
      let hcfTemp = hcf nTemp dTemp
      { n = nTemp / hcfTemp; d = dTemp / hcfTemp }

   // Adds a positive integer and a fraction.
   static member (+) (i : uint32, f2: Fraction) =
      let nTemp = f2.n + i * f2.d
      let dTemp = f2.d
      let hcfTemp = hcf nTemp dTemp
      { n = nTemp / hcfTemp; d = dTemp / hcfTemp }

   // Subtract one fraction from another.
   static member (-) (f1 : Fraction, f2 : Fraction) =
      if (f2.n * f1.d > f1.n * f2.d)
        then failwith "This operation results in a negative number, which is not supported."
      let nTemp = f1.n * f2.d - f2.n * f1.d
      let dTemp = f1.d * f2.d
      let hcfTemp = hcf nTemp dTemp
      { n = nTemp / hcfTemp; d = dTemp / hcfTemp }

   // Multiply two fractions.
   static member (*) (f1 : Fraction, f2 : Fraction) =
      let nTemp = f1.n * f2.n
      let dTemp = f1.d * f2.d
      let hcfTemp = hcf nTemp dTemp
      { n = nTemp / hcfTemp; d = dTemp / hcfTemp }

   // Divide two fractions.
   static member (/) (f1 : Fraction, f2 : Fraction) =
      let nTemp = f1.n * f2.d
      let dTemp = f2.n * f1.d
      let hcfTemp = hcf nTemp dTemp
      { n = nTemp / hcfTemp; d = dTemp / hcfTemp }

   // A full set of operators can be quite lengthy. For example,
   // consider operators that support other integral data types,
   // with fractions, on the left side and the right side for each.
   // Also consider implementing unary operators.

let fraction1 = { n = 3u; d = 4u }
let fraction2 = { n = 1u; d = 2u }
let result1 = fraction1 + fraction2
let result2 = fraction1 - fraction2
let result3 = fraction1 * fraction2
let result4 = fraction1 / fraction2
let result5 = fraction1 + 1u
printfn "%s + %s = %s" (fraction1.ToString()) (fraction2.ToString()) (result1.ToString())
printfn "%s - %s = %s" (fraction1.ToString()) (fraction2.ToString()) (result2.ToString())
printfn "%s * %s = %s" (fraction1.ToString()) (fraction2.ToString()) (result3.ToString())
printfn "%s / %s = %s" (fraction1.ToString()) (fraction2.ToString()) (result4.ToString())
printfn "%s + 1 = %s" (fraction1.ToString()) (result5.ToString())
  

Operátory na globální úrovni

Můžete také definovat operátory na globální úrovni.Následující kód definuje operátor +?.

let inline (+?) (x: int) (y: int) = x + 2*y
printf "%d" (10 +? 1)

Výstup výše uvedený kód je 12.

Předefinovat běžné aritmetické operátory tímto způsobem, protože oboru pravidla pro F# diktovat, že nově definovaný operátory přednost vestavěné operátory.

Klíčové slovo inline se často používá globální operátory, které jsou často malé funkce, které nejlépe integrovány do volající kód.Vložené funkce operátor provedení také jim umožňuje pracovat s parametry typu staticky vyřešen vyrábět staticky přeložit obecný kód.Další informace naleznete v tématu Vložené funkce (F#) a Staticky vyřešen parametry typu (F#).

Viz také

Další zdroje

Členy (F#)