LoginSignup
4
4

More than 1 year has passed since last update.

JavaからVB.NETへ ―書き方対照メモ―

Last updated at Posted at 2020-07-25

この記事について

作成の経緯

新人研修で3ヶ月間Javaをやってきたけれども、配属先部署で使う言語はVisual Basic .NETだったので新しく学ぶ必要が生じた。
しかし、「JavaからVB.NETへ移行」というケースはそんなにないのか(今ならC#あたりが普通…?)、文法の比較などを細かくしているサイトが見つからなかったため、自分で書いてみることにした。

対象者・目的

  • Javaの書き方やプログラミングの諸概念は一通り理解している
  • これからVB.NETでもプログラムを書けるようになりたい

という人(まあ自分と数名の同期だけれど)にJavaとVB.NETの比較対象リファレンスを提供する。

環境

  • Windows 10
  • Visual Studio 2019
  • .NET Framework 4.7.2

といっても、環境に依存するようなコードはほぼないはず。

記述上の注意

  • Visual Basic .NET(VB.NET)のことは、以下単に「VB」と呼ぶ。
  • 同じセクションにあるJavaとVBのコードは、基本的に同じ処理になるようにしている。

参考文献(総合)

コードの基本構造

main

Main.java
public class Main {
    public static void main(String[] args) {
        System.out.println("Hello Java!");
        int a; String b; double c;
    }
}
  • ブロックは {} で区切られる
  • public などの修飾子は小文字
  • ;で文を終える(改行それ自体は意味をもたない)
Form1.vb
Public Class Form1
    Private Sub ShowMessage(sender As Object, e As EventArgs) _ 
    Handles Button1.Click
        Console.WriteLine("Hello VB!")
        Dim a As Integer : Dim b As String : Dim c As Double
    End Sub
End Class
  • ブロックは (修飾子) ClassEnd Class のように分けられる
  • 行の終わりは文(ステートメント)の終わり。
    • 長い文中で意図的に改行させたいときは、行継続文字 _ を入れる
    • ただし、VB2010からは、特定の条件下で行継続文字がなくても改行できるようになった(暗黙の行継続)。
    • 詳しいルールはVisual Basic 2010の新機能 - @ITを参照
  • 1行の中に複数のステートメントを入れたいときは、 : で区切る。

コメント

Comment.java
// 単数行コメント

/*
 * 複数行コメント
 */
Comment.vb
' 単数行コメント

※VBに複数行コメントはない

ドキュメンテーションコメント

専用ツールでAPIドキュメントを生成したり、メソッド名上マウスオーバーで説明を表示したりできるやつ。

  • Java: Javadoc形式で記述する。 /** ~ */
    • Eclipseでは、対象メンバにカーソルを当ててから Alt+Shift+J で生成できる
JavaDoc.java
/**
 * 引数で指定された2つの整数をかけ算し、その結果を返す。
 * @param a  かける数1
 * @param a  かける数2
 * @return かけ算の結果
 */
public static int doCalc(int a, int b) {
    return a * b;
}
  • VB: XMLで記述する。 '''
    • Visual Studioでは、 対象メンバのすぐ上の行で ''' と打つと生成できる。
XmlDoc.vb
''' <summary>
''' 引数で指定された2つの整数をかけ算し、その結果を返す。
''' </summary>
''' <param name="a">かける数1</param>
''' <param name="b">かける数2</param>
''' <returns>かけ算の結果</returns>
Public Shared Function DoCalc(a As Integer, b As Integer) As Integer
    Return a * b
End Function

参考

ファイル・フォルダ構成

※一部省略あり

Java (Eclipse)の例

  • JavaProject
    • bin
    • package
      • Main.class(ビルドされたJavaバイトコード)
    • src
    • package
      • main.java(ソースコード)
    • lib
    • doc
    • .project (Eclipseプロジェクトファイル)
    • .settings
    • .classpath

VB.NET Windows フォーム アプリケーション(Visual Studio)の例

  • VisualStudioSolution
    • VisualStudioSolution.sln (VSソリューションファイル)
    • FirstProject
    • FirstProject.vbproj (VBプロジェクトファイル)
    • bin
      • Debug
      • FirstProject.exe (ビルドされたデバッグ用実行ファイル)
      • Release
    • My Project
    • obj
    • App.config
    • Form1.vb (ソースコード[動作])
    • Form1.Designer.vb (ソースコード[デザイン])
    • SecondProject
    • (FirstProjectと同様)

Visual Studioでは、複数のプロジェクトをソリューションとしてまとめることができる。(Eclipseでもワーキング・セットというものもあるが)

変数

データ型分類

  • Java
    • 基本型(byte, short, int, long, float, double, char, boolean
    • 参照型(Stringなど)
  • VB
    • 値型(Byte, Short, Integer, Long, Single(float相当), Double, Decimal(10進型), Char, Boolean, Date など)
    • 参照型(String など)

日付型は、Javaではjava.util.Datejava.util.Calenderjava.timeなどの標準APIを使う必要がある(つまり必然的に参照型になる)。しかしVBでは、日付・時刻を管理できるDateを標準で用意している。

宣言・アクセス修飾

DeclareVariable.java
int number; // package private
String message; // package private
public int publicNumber;
private String privateMessage;
DeclareVariable.vb
Dim Something ' Private
Dim Number As Integer ' Private
Dim Message As String ' Private
Public PublicNumber As Integer

VB標準設定では、変数の宣言時に型の指定を省略することができる。その場合、初期値のデータ型に従って自動的に変数のデータ型も決められる(型の推定)。初期値がない場合はObject型とみなされる。Option Strict Onにすると、型の推定は無効になる。

変数名の規則

文字 Java VB 備考
半角英数字
日本語文字 もちろんあまり推奨されない
_ アンダースコア
& ×
先頭が数字 × ×

初期化

InitiarizeVariable.java
int number = 100; 
String message = "Hello"; 

InitiarizeVariable.vb
Dim Number As Integer = 100
Dim Message As String = "Hello"
Dim Pi = 3.14 ' 自動的にDouble型として扱われる
Dim BlankNumber As Integer ' 初期値は自動的に「0」になる
Dim BlankMessage As String ' 初期値は自動的に「Nothing」になる

定数宣言

Constant.java
final int MAX_STOCK = 100;
public static final String VERSION_ID = "v1.0.1-RELEASE";
Constant.vb
Const MAX_STOCK As Integer = 100
Const VERSION_ID As String = "v1.0.1-RELEASE" ' ConstステートメントではSharedは使えない

参考

演算子

算術演算子

機能 Java VB.NET 備考
加算 a + b a + b
減算 a - b a - b
乗算 a * b a * b
除算 a / b a / b
整数除算(商) N/A a \ b [VB] aとbはどちらも整数型でなければならない。
23 \ 5 の結果は4になる
剰余(余り) a % b a Mod b 23 % 5 ないし 23 Mod 5 の結果は3になる
累乗 (演算子としてはなし) a ^ b VBの^は算術演算子の中で優先順位が最も高いことに注意
インクリメント ++a または a++ N/A VBではa += 1などど書くしかない
インクリメント --a または a-- N/A VBではa -= 1などど書くしかない

整数同士の除算

Javaでは、割られる数aと割る数bの両方が整数だと、結果の小数点以下が切り捨てられ、整数になる。これは代入先がdouble型などの変数であっても変わらない。

DivideInteger.java
double x;
x = 23 / 5; // xは4.0になる

少なくとも片方が小数(倍精度浮動小数点数)だと、結果も小数になる。

java.DivideDouble.java
double x;
x = 23 / 5.0 // xは4.6になる

一方、VBではできるだけ精度が落ちないように演算が行われる。

DivideInteger.vb
Dim x As Double
x = 23 / 5 ' xは4ではなく4.6になる

VBでもJavaのように整数同士の除算をしたい場合に、\演算子を使う。
vb:DivideWithBackSlashOperator.
Dim x As Double
x = 23 \ 5 ' xは4になる

Javaにおける累乗

Javaでは、 java.lang.Math.pow(a, b) を使う。
第1引数aが底、第2引数bが指数(つまりVBでいうところの a ^ b)。

代入演算子

機能 Java VB.NET 備考
そのまま代入 a = b a = b
加算結果を代入 a += b a += b
減算結果を代入 a -= b a -= b
乗算結果を代入 a *= b a *= b
除算結果を代入 a /= b a /= b
整数除算の結果を代入 N/A a \= b
剰余(余り)を代入 a % b N/A [VB]Modに対応するものはない

(ビット演算系は省略)

比較演算子

機能 Java VB.NET 備考
aはbよりも小さい a < b a < b
aはb以下 a <= b a <= b
aはbよりも大きい a > b a > b
aはb以上 a >= b a >= b
aはbに等しい a == b a = b VBでは=は1個
aはbに等しくない a != b a <> b

論理演算子

以下の表ではABは条件式(True/Falseを返す式)を表す。

論理 機能 Java VB.NET
論理積(AND) AかつB N/A A And B
論理積(AND) AかつB(短絡評価) A && B A AndAlso B
論理和(OR) AまたはB N/A A Or B
論理和(OR) AまたはB(短絡評価) A && B A OrElse B
論理積(NOT) Aでない !A Not A
排他的論理和(XOR) AまたはB、しかしAかつBではない ^A A Xor B

短絡評価:
AがFalseなら条件式全体がFalseになることが確定するので、Bを評価せずに先へ進むこと。
このとき、Bに何らかのメソッドが書いてあっても実行されない。
これを利用して、AがTrueにならないとエラーになる式をBに書くことができる。
例: If Integer.TryParse(str, num) AndAlso num < 5 Then ...

連結演算子

Javaでは文字列の連結に + を使うが、VBでは & を使う。

VBでも+で文字列連結をすることは可能だが、片方が文字列型でない場合に意図しない結果となったり、エラーになる可能性があるため、Microsoftは&の使用を推奨している。

演算子の参考ページ

型変換

条件分岐

if文 / Ifステートメント

ConditionalBranch.java
if (age < 20) canBuyAlcohol = true;

if (age < 13) {
    fareType = "child";
} else if (age < 18) {
    fareType = "student";
} else {
    fareType = "adult";
}

ConditionalBranch.vb
If age < 20 Then canBuyAlcohol = True ' 1行ならばEnd Ifはいらない

If age < 13 Then
    FareType = "child"
ElseIf age < 18 Then
    FareType = "student"
Else
    FareType = "adult"
End If

VBでは、次のように「:」を使って複数のステートメントを1行に書くことも可能。

ConditionalBranchInOneLine.vb
If 20 < age Then FareType = "adult" : CanBuyAlcohol = true Else CanBuyAlcohol = false

Switch / Select Caseステートメント

1つの値と一致させる

ConditionalBranch2.java
switch (num) {
    case 1:
        gender = "男性";
        break;
    case 2:
        gender = "女性";
        break;
    case 3:
        gender = "その他";
        break;
    default:
        gender = "未回答";
        break;
}

switch文の式(上記のnum)は、基本型+String型(Java SE 7以降)のみ。

ConditionalBranch2.vb
Select Case Num
    Case 1
        Gender = "男性"
    Case 2
        Gender = "女性"
    Case 3
        Gender = "その他"
    Case Else
        Gender = "未回答"
End Select

複数の値に一致させる

ConditionalBranch3.java
switch (phoneNumberPrefix) {
    case 090:
    case 080:
    case 070:
        isMobile = true;
        break;
    default:
        isMobile = false;
        break;
}
ConditionalBranch3.vb
Select Case PhoneNumberPrefix
    Case 090, 080, 070
        IsMobile = true
    Case Else
        IsMobile = false
End Select

値の範囲を指定する

ConditionalBranch4.java
// JavaのSwitch文ではできない(やるとしても別の変数を噛ませるしかない)
ConditionalBranch4.vb
Select Case MonthNumber
    Case 3 To 5
        Season = "春"
    Case 6 To 8
        Season = "夏"
    Case 9 To 11
        Season = "秋"
    Case Else
        Season = "冬"
End Select

比較演算子を使う

ConditionalBranch5.java
// JavaのSwitch文ではできない(素直にif文使った方が良い)
ConditionalBranch5.vb
Select Case Score
    Case Is < 60
        Grade = "F"
    Case Is < 70
        Grade = "C"
    Case Is < 80
        Grade = "B"
    Case Is < 90
        Grade = "A"
    Case Else
        Grade = "S"
End Select

繰り返し

for文 / Forステートメント

ForLoop.java
for (int i = 0; i <= 9; i++) {
    System.out.println(i + "回目の繰り返し処理です");
}
ForLoop.vb
For i As Integer = 0 To 9 Step 1 ' 増分値1の場合、Stepは省略可能
    Debug.WriteLine(i & "回目の繰り返し処理です")
Next

どちらの言語でも、For文の初期化式内でループカウンタを宣言するのではなく、For文の外で宣言した変数を使うこともできる。その場合、For文を抜けてもその変数を使うことができる。

ForLoop2.java
int i;
for (i = 0; i <= 9; i++) {
    System.out.println(i + "回目の繰り返し処理です");
}
System.out.println(i + "回繰り返されました");
ForLoop2.vb
Dim i As Integer
For i = 0 To 9 Step 1 ' 増分値1の場合、Stepは省略可能
    Debug.WriteLine(i & "回目の繰り返し処理です")
Next
Debug.WriteLine(i & "回繰り返されました")

拡張for文 / For-Eachステートメント

ForEachLoop.java
int[] scoreArray = {70, 80, 90};

// 通常のfor文
for (int i = 0; i < scoreArray.length(); i++) {
    System.out.println(scoreArray[i]);
}

// 拡張for文
for (int score : scoreArray) {
    System.out.println(score);
}
ForEachLoop.vb
Dim ScoreArray() As Integer = {70, 80, 90}

' 通常のfor文
For i As Integer = 0 To UBound(ScoreArray) 
    Debug.WriteLine(ScoreArray(i))
Next

' For Eachステートメント
For Each score As Integer In ScoreArray
    Debug.WriteLine(score)
Next

while文 / While-End Whileステートメント

条件がtrueである限り実行し続ける。

WhileLoop.java
int i = 0;
while (i < 10) {
    System.out.println(i + "回目の繰り返し処理です");
    i++;
}
WhileLoop.vb
Dim i As Integer = 0
While i < 10
    Debug.WriteLine(i & "回目の繰り返し処理です")
    i += 1
End While

※このサンプルではWhileよりもForのほうが適している

do-while文 / Do-Loopステートメント

後判断型(1回は実行される)

DoWhileLoop.java
Random rd = new Random();
int num = 0;
do {
    num = rd.nextInt(100) + 1;
    System.out.println(num);
} while (num % 2 == 0);
DoLoopWhile.vb
Dim rd As Random = new Random()
Dim Num As Integer = 0

Do
    Num = rd.Next(1, 100)
    Debug.WriteLine(Num)
Loop While Num Mod 2 = 0

VBでは、Loop While 条件 (条件がfalseになるまで繰り返す)のほか、Loop Until 条件(条件がtrueになるまで繰り返す)というのも使える。

DoLoopUntil.vb
Dim rd As Random = new Random()
Dim Num As Integer = 0

Do
    Num = rd.Next(1, 100)
    Debug.WriteLine(Num)
Loop Until Num Mod 2 <> 0

Until以下の条件が逆転しているが、DoLoopWhile.vbDoLoopUntil.vbはどちらも同じ処理になる。

前判断型(1回も実行されない可能性がある)

DoLoopWhile2.vb
Dim i As Integer = 0
Do While i < 10
    Debug.WriteLine(i & "回目の繰り返し処理です")
    i += 1
Loop
DoLoopUntil2.vb
Dim i As Integer = 0
Do Until i >= 10
    Debug.WriteLine(i & "回目の繰り返し処理です")
    i += 1
Loop

ループを抜ける

  • Javabreak;
  • VB:Exit DoExit ForExit While

途中で次の繰り返しに進む

  • Java:continue;
  • VB:Continue DoContinue ForContinue While

配列

宣言

カッコの中で指定する数字の意味が違う点に注意。

ArrayDecralation.java
int[] numArray = new int[5];

インデックス 0, 1, 2, 3, 4 の合計5個の要素を持った配列になる。
[n] で指定するのは配列の要素数

ArrayDeclaration.vb
Dim NumArray(4) As Integer

インデックス 0, 1, 2, 3, 4 の合計5個の要素を持った配列になる。
(n) で指定するのはインデックスの最大値

初期化

ArrayInit.java
int[] numArray = { 10, 20, 30, 40, 50 };
ArrayInit.vb
Dim NumArray() As Integer = { 10, 20, 30, 40, 50 }

代入・利用

ArrayUse.java
numArray[3] = 31;

int a = numArray[3];
ArrayUse.vb
NumArray(3) = 31

Dim a As Integer = NumArray(3)

多次元配列

MultiDArray.vb
int[][] numArray = new int[3][4];
double[][] doubleArray = { { 0.0, 0.1, 0.2 }, { 1.1, 2.2, 3.3, 4.4 } };
MultiDArray.vb
Dim NumArray(2, 3) As Integer
Dim DoubleArray(, ) As Double = { { 0.0, 0.1, 0.2 }, { 1.1, 2.2, 3.3, 4.4 } }

(, )は一見するとインデックス最大値を入れ忘れているようにも見えるが、Javaでいう[][]に相当するもの。

配列サイズの変更

Javaでは一度作った配列のサイズを変更することはできず、新たに配列を作ってそこに値を移し替えるしかない。

しかし、VBではReDimステートメントを使うことで配列のサイズを変更できる。

ChangeArraySize.vb
Dim NumArray(9) As Integer

' ...

ReDim Preserve NumArray(6)

Preserve を付けると、元の要素の値が保持される(付けないと全ての要素が空になる)。
要素数を減らした場合、減らされた分の要素は削除される(上記例では、インデックス7, 8, 9の3要素は削除される)。

配列の長さ(要素数)

  • Java
    • 配列名.length (要素数を返す) を使う。
ArrayLength.java
int[] numArray = new int[5];

for (int i = 0; i < numArray.length; i++) {
    numArray[i] = i; 
}
// 配列の中身は {0, 1, 2, 3, 4} になる
  • VB:
    • 配列名.Length要素数を返す)を使う。
    • 繰り返しで全要素を処理する場合は、 UBound(配列名)インデックスの最大値を返す)を使う。
    • For文の To< ではなく <= の意味。
    • したがって、 0 To 配列名.Length と書くと、最終回で配列の長さを突き抜けてしまい System.IndexOutOfRangeException になる。
    • どうしてもUBound() を覚えたくなければ、配列名.Length - 1でもいけなくはないが…
ArrayLength.java
Dim NumArray(4) As Integer

For i As Integer = 0 To UBound(NumArray)
    NumArray(i) = i
Next
' 配列の中身は {0, 1, 2, 3, 4} になる

メソッド / プロシージャ

概念の整理(整理し切れていない)

基本的に、「メソッド」=「プロシージャ」だと思っても実用上は困らない。

Javaでは「メソッド」しか出てこないのに対して、VBではどちらの単語も登場する。やっていることは同じ「一連の処理をまとめる」ということだが、「メソッド」は、プロシージャの中でもその所属元を意識している言葉、らしい。

「オブジェクト」が持つ「性質」(フィールド)と「機能」(メソッド)、という感じ。

ただ、英語で "what is the difference between a method and a procedure in visual basic" ってググると、"method vs procedure" じゃなくて "function vs procedure" って書いてあるページばかりがヒットする(method = function?)
このあたりはプログラム言語の歴史(関数 function とか サブルーチン subroutine)にかかわってきそう。

参考

用語の比較

対象 Java VB
戻り値を返さない処理 メソッド(void Subプロシージャー
戻り値を返す処理 メソッド(void以外) Functionプロシージャー
クラスフィールドの読み書きをする処理 getter/setterメソッド Propertyプロシージャー
個々のインスタンスに属する処理 インスタンスメソッド (普通のSub/Functionプロシージャー)
クラス全体に属する処理 staticメソッド 共有(Shared)メソッド
イベントに応じた処理 N/A イベントハンドラー(Subプロシージャーの一形態)

Subプロシージャー

戻り値を返さない 処理。(直接の戻り値がないだけなので、参照渡しを使って呼び出し元に存在する変数やオブジェクトを書き換え、データを返すようなことは可能)

  • Java: アクセス修飾子 [static] void 名前(型名 引数名, ...) {}
VoidMethod.java
public void showMessage(int a, int b) {
    System.out.println(a + b);
}
  • VB: アクセス修飾子 [Shared] Sub 名前(引数名 As 型名, ...)End Function
    • イベントハンドラーもここに属する(後ろに Handles句が付くやつ)
SubProc.vb
Public Sub ShowMessage(Str1 As String, Str2 As String)
    Debug.WriteLine(a + b)
End Sub

Functionプロシージャー

戻り値を返す処理。

  • Java: アクセス修飾子 [static] 戻り値の型 名前(型名 引数名, ...) {}
    • return で戻り値を指定する
ReturnMethod.java

public int doCalc(int a, int b) {
    return a * b;
}
  • VB: アクセス修飾子 [Shared] Function 名前(引数名 As 型名, ...) As 戻り値の型End Function
    • Return で戻り値を指定する
FunctionProc.vb
Public Function DoCalc(a As Integer, b As Integer) As Integer
    Return a * b
End Function

Propertyプロシージャー

→ クラスの項目で解説

プロシージャーを途中で抜ける

ExitMethod.java
public void showMessage() {
    if (errFlag) {
        return; // 実はvoidメソッドでもこれで抜けられる
    } else {
        System.out.println("処理成功")
    }
}

public int doCalc(int a, int b) {
    int result = a * b;
    if (result > 10) {
        return 0; // 値を返さずに抜けることは許されない
    } else {
        return result;
    }
}
ExitProcedure.vb
Public Sub ShowMessage() 
    If ErrFlag Then
        Exit Sub ' VBではExit Sub
    Else
        Debug.WriteLine("処理成功")
End Sub

Public Function DoCalc(a As Integer, b As Integer) As Integer
    Dim result As Integer = a * b
    If (result > 10) Then
        Exit Function ' 戻り値がInteger型なので0を返す
    ElseIf (result > 50) Then
        DoCalc = result + 1
        Exit Function ' 変数DoCalcに設定した値を返す
    Else
        Return result
    End If
End Function

Javaだとreturnせずにvoid以外のメソッドを抜けることは不可能だが、VBのFunctionプロシージャーではできてしまう。
ただし、戻り値の型によってはぬるぽ例外を発生させるなど、予期しない動作を招く原因になりかねないので、必ずReturnすべきと思われる。

可変長引数

  • Java: 引数を (データ型... 変数名)とする
    • 当該メソッド内では、配列変数のように扱うことができる
    • 他の引数も指定する場合、可変長引数は引数リストの最後に置かなければならない
VariadicMethod.java
public static int getSum(int... numbers) {
    int sum = 0;
    for (int i = 0; i < numbers.length; i++) {
        sum += numbers[i];
    }
    return sum;
}
  • VB: (ParamArray 変数名 As データ型[]) とする
    • 性質はJavaと同じ。
VariadicFunction.vb
Public Shared Function GetSum(ParamArray Numbers As Integer[]) As Integer
    Dim Sum As Integer = 0
    For i As Integer = 0 To UBound(Numbers)
        Sum += Numbers(i)
    Next i
    Return sum;
End Function 

可変長引数の参考文献

オブション引数

呼び出し時に省略可能な引数。

  • Java: (たぶん)言語仕様として持っていない。
    • Java 8 から導入されたOptional型は、全く違う概念なので混同しないこと。
  • VB: (Optional 変数名 As データ型 = 既定値) とする
    • 呼び出し時に省略された場合、既定値が渡されたものとみなされる。
    • なので既定値は必ず指定しておく必要がある。
    • Optionalを指定した引数移行のすべての引数は、Optionalでなければならない(省略できない引数を全て書いた後、Optional引数を書く)
    • Optional引数を複数設けること自体はOK。
OptionalArguments.vb
Public Shared Function Calc(Num1 As Integer, Num2 As Integer, Optional CalcMethod As Integer = 0)
    If CalcMethod = 0 Then
        Return Num1 + Num2
    ElseIf CalcMethod = 1 Then
        Return Num1 - Num2
    ElseIf CalcMethod = 2 Then
        Return Num1 * Num2
    ElseIf CalcMethod = 3 Then
        Return Num1 / Num2
    Else
        Return 0
    End If
End Function

この例では、Calc(5, 10)のように呼び出した場合、CalcMethod = 0のパターン(つまり足し算)が実行される。

返り値として複数の値を受け取る

  • Java: クラスにまとめて、そのオブジェクトを返すしかない。
ReturnMultiValue.java
public static Result getResult(int a, int b) {
    Result result = new Result();
    result.setSum(a + b);
    result.setDiff(a - b);
    result.setProduct(a * b);
    result.setQuotient((double) a / b);
    Return result;
}
Result.java
public Class Result {
    int Sum;
    int Diff;
    int Product;
    double Quotient;

    // getter / setter 
}
  • VB: タプルを利用して複数の値を返すことができる
    • タプル:その場で複数の変数を1つにまとめたもの
    • 臨時のクラスを作る、というイメージだと分かりやすいだろうか
Tuple.vb
Public Sub Main()
    ' タプルを名前付きで宣言
    Dim Result As (Sum As Integer, Diff As Integer, Product As Integer, Quotient As Double)

    Result = GetResult(5, 10)

    ' タプルに入った値を利用
    Debug.WriteLine(Result.Sum)
    Debug.WriteLine(Result.Diff)
    Debug.WriteLine(Result.Product)
    Debug.WriteLine(Result.Quotient)
End Sub

' タプルを返すFunctionプロシージャー
Public Shared Function GetResult(a As Integer, b As Integer) As (Integer, Integer, Integer, Double)
    Return (a + b, a - b, a * b, a / c)
End Function

エントリポイント

プログラムが起動されたときに、最初に実行されるメソッド。

Javaはmainと名の付くメソッドが必ずエントリポイントになるが、VBではそうとは限らない。Windows Formsプロジェクトを作成すると、最初に作成したフォームがエントリポイントになる。これを変更する方法については、JavaのmainメソッドをVB.NETで作成してみる! | ライズウィルスタッフブログが詳しい。

クラス

構成

  • Javaクラス public class Main{ }
    • フィールド
    • メソッド
    • getter/setterメソッド

※JavaBeansの形式に従った例。

JavaClass.java
public class JavaClass {
    // フィールド(オブジェクトの状態/性質を示すもの)
    private int field;

    // メソッド(オブジェクトの動作・振る舞いを示すもの)
    public void method(){
        // ...
    }

    // メソッド > getter(カプセル化されているprivateフィールドの読み取り機能を提供)
    public int getField() {
        return field;
    }

    // メソッド > setter(カプセル化されているprivateフィールドへの書き込み機能を提供)
    public void setField(int value) {
        this.field = value;
    }
}
  • VBクラス Public Class Main ... End Class
    • フィールド(メンバ変数)
    • プロパティとの区別のために、_を接頭辞として付ける場合がある
    • プロパティ
    • Getプロシージャー
    • Setプロシージャー
    • プロシージャ(メソッド)
    • イベント
VBClass.vb
Public Class VBClass
    ' フィールド(メンバー変数)
    Dim _field As Integer

    ' プロパティ
    Property field() As Integer
        Get
            Return _field
        End Get
        Set(ByVal value As Integer)
            _field = value
        End Set
    End Property

    ' プロシージャー
    Public Sub Procedure()
        ' ...
    End Sub
End Class

プロパティについてもっと詳しく

基本

プロパティは、Javaでいうところのgetter/setterメソッドをまとめたもの(Getプロシージャ・Setプロシージャのうち片方だけを実装することもできる)。
Javaと異なるのは、プロパティは当該クラスの外からはフィールドのように扱われるという点である。

たとえば、上記サンプルコード JavaClass.java の プライベートフィールド field に他のクラスからアクセスするときには、次のようなコードを書く必要がある。

AccessToField.java
public class Main {
    public static void main(String[] args) {
        JavaClass jc = new JavaClass();

        // 以下2行はコンパイルエラーになる
        int num = jc.field;
        jc.field = 100;

        // 代わりに、こう書く
        int num = jc.getField();
        jc.setField(100);
    }
}

このように、オブジェクト変数名.フィールド名 ではアクセスが拒否されるので、代わりにgetterメソッドの返り値としてフィールドの内容を受け取ったり、setterメソッドに値を引数として渡すことでフィールドの内容を書き換えるというやり方になる。

これと同じような動きをVBで書くと、こうなる。

AccessToField.vb
Public Class Main
    Public Shared Sub Main
        Dim vbc As New VBClass()

        Dim num As Integer = vbc.field 'Get呼び出し
        vbc.field = 100 'Set呼び出し
    End Sub
End Class

プロパティ名をフィールドのように書くことで、そのプロパティに定義されたGet/Setプロシージャーが暗黙的に呼び出される。

自動実装プロパティ

なお、単に値を返す/書き込むだけのプロパティであれば、自動実装プロパティを使うことでコードを簡略化できる。

AutoImplProperty.vb
Public Class AutoImplProperty
    Public Property Name As String
    Public Property Owner As String = "DefaultName"
    Public Property Items As New List(Of String) From {"M", "T", "W"}
    Public Property ID As New Guid()
End Class

自動実装プロパティ - Visual Basic | Microsoft Docs より)

このとき、プロパティ名に_を付けた隠しPrivateフィールド(バッキング フィールド)が自動的に作成される。上記の例では、_Name, _Owner, _Items, _ID というバッキングフィールドが作成される(従って、自分でこれらと同じ名前のフィールドを宣言するとコンパイルエラーになる)

プロパティ:フィールド = 1:n もOK

また、プロパティはフィールドと1対1で対応している必要はない。言い換えると、複数のフィールドから値を拾ってきて、連結して1つのフィールドのように扱うこともできる。また、1つのまとまった値を受け取り、実際には2つ以上のフィールドに分割して格納する、ということもできる。(もちろんそれに見合ったGet/Setプロシージャを定義しておく必要はある)。
Microsoft Docsにわかりやすい例があったので、引用する(クラス内のメンバであることが分かりやすいよう、Public Class ~ End Classを付加している)。

次のプロパティは、フル ネームを 2 つの構成要素名 (名と姓) として格納します。 呼び出し元のコードが fullName を読み取ると、Get プロシージャが 2 つの構成要素名を結合し、フル ネームを返します。 呼び出し元のコードが新しいフル ネームを割り当てると、Set プロシージャがそれを 2 つの構成要素名に分割することを試みます。 スペースが見つからない場合は、すべてが名として格納されます。.
Property プロシージャ - Visual Basic | Microsoft Docs

CombinedProperty.vb
Public Class CombinedProperty
    Private firstName As String
    Private lastName As String

    Property fullName() As String
        Get
        If lastName = "" Then
            Return firstName
        Else
            Return firstName & " " & lastName
        End If

        End Get
        Set(ByVal Value As String)
            Dim space As Integer = Value.IndexOf(" ")
            If space < 0 Then
                firstName = Value
                lastName = ""
            Else
                firstName = Value.Substring(0, space)
                lastName = Value.Substring(space + 1)
            End If
        End Set
    End Property
End Class

呼び出し側:

CallProperty.vb
fullName = "MyFirstName MyLastName"
MsgBox(fullName)

その他、プロパティとメンバ変数の違いについては以下のページも参照。

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4