tamuです。
Apex入門記事です。
「JavaやってたからApexも書けるよね」と言われても大丈夫なように、主にJavaと違う部分についてまとめています。
package について
Javaでいうところの package はありません。
AppExchange を開発する際にその AppExchange を識別するための名前空間(namespace)を登録することはありますが、それもJavaでいうところの package ではありません。
package は存在しない、と思っておきましょう。
class の書き方
↓ ここにすべてが書いてあるのですが抜粋して説明します。
| |
アクセス範囲
global
- すべての Apex クラスからアクセス可能
- 外部から呼び出すような class に使う
globalを使うことはあまりお勧めしないとのこと
これは Java にはないです。
ほとんどの場合で global が必要なことはないので、次で説明する public を使っておきましょう。
逆にいうと global がついている class は「外部から呼び出される class」と思って読んでおきましょう。
public
- 同じ名前空間であればアクセス可能
- トップレベルでクラス宣言をするのであればこれを指定しておけば良い
テストコードじゃないコードは public をつけてクラス宣言をすれば良いです。
「同じ名前空間であれば」とあるのは、たとえば AppExchange のクラスが public で宣言してあれば、AppExchange 外のクラスは AppExchange のクラスを読んだり実行したりすることはできません。
private
- 外から参照しない inner class だったらこれをつければ良い
- テストコードはトップレベルで宣言するときにつける
privateと(何もつけない)は同じ扱い
余談
Java でいうところの static class はありません。
Java で inner class を static で定義するとこのように書きますが、
| |
Apex では inner class はこのように書きます。
| |
アクセス権限
Apex クラスがアクセスするレコードの取り扱いについて定義します。
sharing rule の範囲で動くのか、 sharing rule を無視して動くのか、のように sharing の語源を頭においておくとイメージしやすいかと思います。
with sharing
- 共有ルールの範囲内でレコードにアクセスできる
- → そのコードを実行したユーザがアクセスできるレコードのみアクセスできる。アクセスできないレコードはアクセスできない
without sharing
- 共有ルールを超えてレコードにアクセスできる
- → そのコードを実行したユーザがアクセスできるレコード以外にも、すべてのレコードにアクセスできる
(何もつけない)
with sharingと同じです- 「必ず付けましょう」 by Salesforce
override させるかどうか
virtual
- 拡張クラス側での
overrideを可能にします
以下は Java であればコンパイルできますが、 Apex ではコンパイルエラーになります。
| |
このように virtual が必要になります。
(Kotlin で class に open を付けないと継承できないのに似てます)
| |
abstract
- 抽象メソッドが含まれることを宣言します
- 抽象メソッドが存在していなくてもこのクラスを直接
newすることはできません - Java でいうところの匿名クラスはないため、かならず実装クラスの定義が必要になります
| |
拡張クラスかどうか
extends
- 元の
virtualクラスまたはabstractクラスを拡張する場合はこれを付けます
Java と同じです。
interface の実装かどうか
implements
interfaceを実装する場合はこれをつけます
Java と同じです。
できないこと
クラス拡張の禁止 (final)
- 拡張禁止を明示することはできません
virtualを付けなければ拡張できないので、それで代用します
ここはKotlinと同じです。
generics
generics は事前に用意されているクラスでしか使えません。 このような宣言ができません。 宣言はできないのですが、キャストはできるので Java 1.3 時代だと思えばなんとかなります。
| |
匿名クラス
abstract のところで触れましたが、 匿名クラスは書けません。
abstract クラスや interface を使うには必ずリテラルに書いた実装クラスが必要になります。
interface の書き方
class 宣言に似てます。
というか Java とほとんど同じです。
| |
アクセス範囲
class のものと同じです。
トップレベルで宣言する場合は global or public を付けましょう。
AppExchange 開発では global な interface はリリースすると変更できないそうなのでお気をつけて。
(https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_classes_interfaces.htm の一番下に書いてあります)
拡張するかどうか
ちゃんとドキュメントには書いてないのですが、 Java と同じように interface を拡張することができます。
(コンパイルは通ります)
がちゃんとドキュメント化されていないので、 interface を拡張するのではなく、 abstract class で implements するほうが良いかなと思います。
| |
余談
私は public な interface を宣言することはあまりありません。
Java で interface を定義するときは、同じI/Fで呼び出したい処理がいろいろなパッケージにまたがるときが多いです。
Apex はパッケージで namespace を分けるわけではないため、その interface を定義するメリットがあまりないためです。