はじめに
Apexは、Salesforce上でビジネスロジックを実装できる、Javaに似たプログラミング言語です。
「Javaに似た」、これはApex 開発者ガイドにある表現
Apex は、変数および式の構文、ブロックおよび条件ステートメントの構文、ループ構文、オブジェクトおよび配列の表記など、よく知られた Java のイディオムに基づいています。
Apex 開発者ガイドより
から読み取れますが、「なにが?どこが?」って思いますよね。
ということで、
今回はクラス定義について書いてみます。
Apexクラス定義
Syntax
1 2 3 4 5 |
private | public | global [virtual | abstract | with sharing | without sharing] class ClassName [implements InterfaceNameList] [extends ClassName] { // ロジック } |
private
テストクラスは、アノテーション「@isTest」と「private」をセットで書くようにしてます。
間違って他クラスからテストクラスを使うことは無いでしょうけど、間違って使われないようにしておくことが大事ですから。
1 2 3 4 |
@isTest private class MyClassTest { // テストロジック } |
あと内部クラスを書く時は、privateの意味合いとして使うことが殆どですが、デフォルトが「private」なので、あえて書かないですね。
1 2 3 4 5 6 |
public class MyClass { // MyClassロジック class MyInnerClass { // MyInnerClassロジック } } |
public
普通にクラスを書く時は「public」を使います。
普通の定義はいろいろあると思いますが、次の「global」では無い時をイメージしてもらうといいかもしれません。
1 2 3 |
public class MyClass { // ロジック } |
global
アプリケーションや名前空間のボーダーを超えたクラスを書く時は「global」を使います。
そんなクラスを書くことは少ないかもしれませんが、分かり易く例えるとすると。何にも依存しない標準的な機能を備えたユーティリティ的なクラスとか。
1 2 3 |
global class MyBorderlessUtilityClass { // 汎用ロジック } |
今回は取り上げませんが、webserviceキーワードで定義されたメソッドを含むクラスは、「global」を使う必要があります。
virtual
拡張や上書きを許可するクラスを書く時は「virtual」を使います。
共通処理などをまとめておいて、それを継承して使わせるようなクラスとしての利用になりますね。
ちなみに「virtual」を使ったクラスは抽象クラスではありませんので、インスタンスを作ることも可能です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
public virtual class MyVirtualClass { public MyVirtualClass() { // コンストラクタ } public virtual void myMethod1() { // 共通化ロジック } public void myMethod2() { // 共通化ロジック } } public class MyClass extends MyVirtualClass { public MyClass() { super(); } public override void myMethod1() { // 上書きロジック } } |
abstract
抽象メソッド(定義のみのメソッド)を含む、拡張や上書きを許可するクラスを書く時は「abstract」を使います。
こちらも共通処理をまとめておいて、それを継承して使わせるようなクラスとしての利用になりますね。
インスタンスを作ることを抑止した基底クラスを実装する時によく使う、と言うとしっくりくるのでは。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
public abstract class MyAbstractBaseClass { public MyAbstractBaseClass() { // コンストラクタ } public abstract void myMethod1(); public void myMethod2() { // 共通化ロジック } } public class MyClass extends MyAbstractBaseClass { public MyClass() { super(); } public override void myMethod1() { // MyClass用ロジック } } |
ちょっと話が逸れますが、「基底クラスに共通処理」という言葉には注意が必要です。
安易に作り込むと、逆に見通しが悪く使い勝手が悪いクラスになってしまいますから、基底クラスとしての役割や範囲はきちんと検討するようにしましょう。
with sharing
Apexクラスはシステムモードで動作するので、実行ユーザに割り当てた共有ルール(アクセス権限ほか)に関係無く、全オブジェクトの全項目にアクセスできてしまいます。
「with sharing」キーワードを使用すると、Apexクラスはユーザモードで動作するので、実行ユーザに割り当てた共有ルール(アクセス権限ほか)で強制実行されるようになります。
(実行ユーザがSalesforce標準画面で見ることのできないレコードは、実装したApexクラスとVisualforce画面でも見ることはできないレコードとして扱える。)
1 2 3 |
public with sharing class MySharingClass { // ロジック } |
without sharing
「with sharing」の逆で、実行ユーザに割り当てた共有ルール(アクセス権限ほか)で強制実行しないのが「without sharing」キーワードになります。
例えば、「with sharing」キーワードを指定しユーザモードで実装された別クラスから、「without sharing」キーワードを指定しシステムモードで実装されたクラスが呼ばれた場合、共有ルール(アクセス権限ほか)の強制実行が解除されるという動作をします。
1 2 3 |
public without sharing class MyNoSharingClass { // ロジック } |
おわりに
内容としては、既に多くの方がまとめられてますし、Salesforceが公開しているApex 開発者ガイドを見ればいいというものだったりする訳ですが、今回あらためて自分の言葉でまとめてみました。
自社のSalesforceエンジニアはもちろん、これを見たSalesforceエンジニアの一助になればいいかな、と思ってます。