ホーム » スタッフ » 斉藤徹 » 講義録 » 情報構造論 » 情報構造論の補講

情報構造論の補講

以下に、私の示す解説 (もしくはGemini による解説) をよく理解したうえで、確認のための Forms に回答せよ。

AIを使って勉強をするのであれば、「プログラミング初心者向けに」とか「Javaにおける」といった前提を明記したプロンプトを使って勉強するべき。

#レポート課題で JavaScript で書かれたコードで提出してくる「何も考えてない」人がいた🤷‍♂️。

プリミティブ型とは

変数とスコープ

オブジェクトとメモリイメージ

C言語の構造体の授業や、Java のクラスオブジェクトの授業の基本を習うと、実際のデータがどのように格納されているか理解が浅い場合があるので、簡単なプログラム例によってオブジェクトの説明を行う。

クラス宣言の基本

class クラス名 {
    // インスタンス変数          // インスタンス変数の前には private, public をつけると
    型名  インスタンス変数1 ;    // public クラス外でも使える
    型名  インスタンス変数2 ;    // private クラスのメソッドの中でしか使えない
                              // という意味になる。
    // クラス変数
    static 型名 クラス変数3 ;

    // コンストラクタの定義
    //  【具体的な値を持ったインスタンスを作る時の処理】
    クラス名( 型名 仮引数4 , 型名 仮引数5 ... ) {
        this.インスタンス変数 = 値 ;
        :
    }
    // メソッドの定義
    型名 メソッド名( 型名 仮引数6 , 型名 仮引数7 ... ) {
        :
    }
}

実際のプログラム例で説明

import java.util.*;

class Person {
    // インスタンス変数
    String name ;                    // 本来なら private String name と書くべき
    int    age ;                     // name , age は、インスタンス変数
                               
    // クラス変数
    public static int count = 0 ;    // クラス変数は複数のインスタンスで共有される、
                                     // 1つの実体をもつ変数。new しなくても使える
    // コンストラクタ
    Person( String n , int a ) {
        this.name = n ;              // this はメソッドの対象となるインスタンス全体を表す暗黙の変数。
        this.age  = a ;              // name = n ; と書いてもいいが、局所変数と混同しないように
        count++ ;                    // this.name = n ; と書くことが多い。
    }
    // メソッド
    public void print() {
        System.out.print( "Name=" + this.name ) ;
        System.out.println( "Age=" + this.age ) ;
    }
    // オブジェクトを文字列に必要に応じて自動的に変換させたい時のメソッド
    // toString() は自動生成されるが、自分で定義しなおす場合は、
    // 「自分でメソッド内容を上書きするよ!」という意味の @Override をつける。
    @Override
    public String toString() {
        return "Name=" + this.name + ",Age=" + this.age ;
    }
}

public class Main {
    public static void main( String[] args ) {
        // 単純なインスタンス(具体的な値の入ったオブジェクト)の生成
        Person tsaitoh = new Person( "t-saitoh" , 61 ) ;
        tsaitoh.print() ;   // インスタンス.メソッド()

        // Person の配列を作る
        Person family[] = new Person[ 2 ] ;
        family[ 0 ] = new Person( "Mitsuki" , 27 ) ;
        family[ 1 ] = new Person( "Ayuka" , 25 ) ;

        // Personのクラス変数 count を参照
        //   クラス変数を参照するには、クラス名.クラス変数
        System.out.println( Person.count ) ;

        // 配列の参照
        for( int i = 0 ; i < family.length ; i++ )
            System.out.println( family[ i ] ) ;  // toString() が自動的に呼び出される。
    }
}

クラスとは、データはこんな構造だよ(データ構造)、データを操作するにはこんな関数(メソッド)を使うよ(手続き) を記載したものであり、具体的に、どんな値が入っているかは、コンストラクタ(データを初期化する関数)で決まる。

クラス(データ構造の設計図)に、具体的な値で代入されたものは、インスタンスと呼ぶ。

イメージ図を描いて理解

次に、上記のプログラムのデータがどのように保存されているかのイメージを描いて理解しよう。

プログラミング初心者の段階で「オブジェクト = データ」という理解の時には、図左のようなイメージで理解していてもいいけど、リスト構造のようなデータ構造を理解するためには、図右のような「オブジェクトとは、データの実体と、データが保存された場所(アドレス/番地)で管理されている」というイメージで理解することが重要。

オブジェクトはデータとデータの場所

上記のプログラムのイメージ図を描いてもらうと、実際のデータをイメージできていない人がいます。

まずは超重要なポイント:

  • プリミティブ型: 変数にその値そのものが代入される。
  • オブジェクト型: データはヒープメモリに保存され、変数にはそのデータの場所(番地)が代入される。
    図中の→は、”このデータはこの番地を指さしている” という意味で描いている。

リスト構造を改めて理解する

import java.util.*;

class ListNode {
    int      data ;  // 保存するデータ
    ListNode next ;  // 次のデータの場所
    ListNode( int x , ListNode n ) {
        this.data = x ;
        this.next = n ;
    }
}

public class Main {
    // リスト表示関数 print()
    public static void print( ListNode p ) {
        for( ; p != null ; p = p.next )
            System.out.print( p.data + " " ) ;
        System.out.println() ;
    }
    public static void main(String[] args) throws Exception {
        // リストの生成
        ListNode top = null ;
        top = new ListNode( 11 , null ) ;
        top.next = new ListNode( 22 , null ) ;
        top.next.next = new ListNode( 33 , null ) ;
        // top = new ListNode( 11 , new ListNode( 22 , new ListNode( 33 , null ) ) ) ;

        // リストの参照
        System.out.println( top.next.next.data ) ;
        System.out.println( top.next.data ) ;
        System.out.println( top.data ) ;

        // リストの表示関数の呼び出し
        print( top ) ;
    }
}

リスト構造の変数 top に new で値が代入されていくイメージを確認してみよう。

上記プログラムは、本来であれば、top = new ListNode( 11, new ListNode( 22, new ListNode( 33 , null ) ) ) ; で記載する処理を、1つづつ代入する形式で示したもの。top や top.next が、データのどの部分を示しているのかを、図で確認すること。

前の説明の、オブジェクトの変数にはアドレスが入っているというイメージで図を描く。

理解度の最終確認として、以下の Forms に回答してください。