This is an automated email from the ASF dual-hosted git repository.

kevingurney pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow.git


The following commit(s) were added to refs/heads/main by this push:
     new 36ddbb531c GH-36953: [MATLAB] Add gateway `arrow.array` function to 
create Arrow Arrays from MATLAB data (#36978)
36ddbb531c is described below

commit 36ddbb531cac9b9e512dfa3776d1d64db588209f
Author: sgilmore10 <[email protected]>
AuthorDate: Thu Aug 3 12:28:27 2023 -0400

    GH-36953: [MATLAB] Add gateway `arrow.array` function to create Arrow 
Arrays from MATLAB data (#36978)
    
    
    
    ### Rationale for this change
    
    As discussed in #36855, we think it would be better to move the recommended 
APIs for the MATLAB Interface directly under the top-level `arrow.*` package. 
This should help simplify the interface, and will make it easier for users to 
switch between multiple language bindings. We have already moved the `type` 
convenience constructors to the `arrow` package.  Now we want to add a gateway 
function that creates arrays to mirror `PyArrow`. As part of this change, we 
will modify the array con [...]
    
    ### What changes are included in this PR?
    
    1. Added `arrow.array()` gateway function that can be used to construct 
arrays:
    
    ```matlab
    >> arrowArray = arrow.array([1 2 3 4]);
    >> class(arrowArray)
    
    ans =
    
        'arrow.array.Float64Array'
    
    >> arrowArray = arrow.array(["A" "B" "C"]);
    >> class(arrowArray)
    
    ans =
    
        'arrow.array.StringArray'
    
    ```
    
    2. Added a static `fromMATLAB()` method to all  subclasses 
of`arrow.array.Array`.
    
    ```matlab
    >> array = arrow.array.StringArray.fromMATLAB(["A" "B" "C"])
    
    array =
    
    [
      "A",
      "B",
      "C"
    ]
    
    >> array = arrow.array.TimestampArray.fromMATLAB(datetime(2023, 8, 1))
    
    array =
    
    [
      2023-08-01 00:00:00.000000
    ]
    
    ```
    
    As part of this change, users can no longer use the `arrow.array.Array` 
subclass constructors to create arrays. Instead, they can use either 
`arrow.array()` or the static `fromMATLAB` method.
    
    ### Are these changes tested?
    
    Updated the existing tests to account for the API changes and added the 
following new test classes:
    
    1. arrow/internal/validate/tType.m
    2. arrow/internal/validate/tShape.m
    3. arrow/internal/validate/tRealNumeric.m
    4. arrow/internal/validate/tNonsparse.m
    5. arrow/internal/validate/tNumeric.m
    6. arrow/array/tArray.m
    
    ### Are there any user-facing changes?
    
    Yes, we changed the signature of all `arrow.array.Array` subclasses to 
accept scalar `libmexclass.proxy.Proxy` classes. NOTE: The MATLAB interface is 
still under active development.
    
    ### Future Directions
    
    1. In a followup PR, we plan on adding a new name-value pair to 
`arrow.array()` called `Type`, which can be set to an `arrow.type.Type` object. 
This will let users specify what kind of arrow array they would like to create 
from MATLAB data.
    
    * Closes: #36953
    
    Authored-by: Sarah Gilmore <[email protected]>
    Signed-off-by: Kevin Gurney <[email protected]>
---
 .../src/matlab/+arrow/+args/validateTypeAndShape.m | 36 ---------
 matlab/src/matlab/+arrow/+array/Array.m            |  7 +-
 matlab/src/matlab/+arrow/+array/BooleanArray.m     | 33 +++++---
 matlab/src/matlab/+arrow/+array/Float32Array.m     | 16 +++-
 matlab/src/matlab/+arrow/+array/Float64Array.m     | 16 +++-
 matlab/src/matlab/+arrow/+array/Int16Array.m       | 16 +++-
 matlab/src/matlab/+arrow/+array/Int32Array.m       | 16 +++-
 matlab/src/matlab/+arrow/+array/Int64Array.m       | 16 +++-
 matlab/src/matlab/+arrow/+array/Int8Array.m        | 16 +++-
 matlab/src/matlab/+arrow/+array/NumericArray.m     | 30 +++++---
 matlab/src/matlab/+arrow/+array/StringArray.m      | 43 +++++++----
 matlab/src/matlab/+arrow/+array/TimestampArray.m   | 38 +++++++---
 matlab/src/matlab/+arrow/+array/UInt16Array.m      | 16 +++-
 matlab/src/matlab/+arrow/+array/UInt32Array.m      | 16 +++-
 matlab/src/matlab/+arrow/+array/UInt64Array.m      | 16 +++-
 matlab/src/matlab/+arrow/+array/UInt8Array.m       | 16 +++-
 .../+validate/nonsparse.m}                         | 24 ++----
 .../Int8Array.m => +internal/+validate/numeric.m}  | 27 +++----
 .../+validate}/parseValidElements.m                |  0
 .../+validate/realnumeric.m}                       | 24 ++----
 .../Int8Array.m => +internal/+validate/shape.m}    | 25 +++---
 .../Int8Array.m => +internal/+validate/type.m}     | 24 ++----
 matlab/src/matlab/+arrow/+tabular/RecordBatch.m    | 41 +---------
 matlab/src/matlab/+arrow/array.m                   | 67 ++++++++++++++++
 matlab/test/arrow/array/hNumericArray.m            | 43 +++++------
 matlab/test/arrow/array/tArray.m                   | 88 ++++++++++++++++++++++
 matlab/test/arrow/array/tBooleanArray.m            | 49 ++++++------
 matlab/test/arrow/array/tFloat32Array.m            | 24 +++---
 matlab/test/arrow/array/tFloat64Array.m            | 28 +++----
 matlab/test/arrow/array/tInt16Array.m              |  2 +-
 matlab/test/arrow/array/tInt32Array.m              |  2 +-
 matlab/test/arrow/array/tInt64Array.m              |  2 +-
 matlab/test/arrow/array/tInt8Array.m               |  2 +-
 matlab/test/arrow/array/tStringArray.m             | 65 ++++++++--------
 matlab/test/arrow/array/tTimestampArray.m          | 64 +++++++++-------
 matlab/test/arrow/array/tUInt16Array.m             |  2 +-
 matlab/test/arrow/array/tUInt32Array.m             |  2 +-
 matlab/test/arrow/array/tUInt64Array.m             |  2 +-
 matlab/test/arrow/array/tUInt8Array.m              |  2 +-
 matlab/test/arrow/internal/validate/tNonsparse.m   | 44 +++++++++++
 matlab/test/arrow/internal/validate/tNumeric.m     | 56 ++++++++++++++
 .../validate}/tParseValidElements.m                |  2 +-
 matlab/test/arrow/internal/validate/tRealNumeric.m | 43 +++++++++++
 matlab/test/arrow/internal/validate/tShape.m       | 69 +++++++++++++++++
 .../arrow/internal/validate/tType.m}               | 29 +++----
 45 files changed, 809 insertions(+), 390 deletions(-)

diff --git a/matlab/src/matlab/+arrow/+args/validateTypeAndShape.m 
b/matlab/src/matlab/+arrow/+args/validateTypeAndShape.m
deleted file mode 100644
index 78e8dd1efe..0000000000
--- a/matlab/src/matlab/+arrow/+args/validateTypeAndShape.m
+++ /dev/null
@@ -1,36 +0,0 @@
-% Licensed to the Apache Software Foundation (ASF) under one or more
-% contributor license agreements.  See the NOTICE file distributed with
-% this work for additional information regarding copyright ownership.
-% The ASF licenses this file to you under the Apache License, Version
-% 2.0 (the "License"); you may not use this file except in compliance
-% with the License.  You may obtain a copy of the License at
-%
-%   http://www.apache.org/licenses/LICENSE-2.0
-%
-% Unless required by applicable law or agreed to in writing, software
-% distributed under the License is distributed on an "AS IS" BASIS,
-% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-% implied.  See the License for the specific language governing
-% permissions and limitations under the License.
-
-function validateTypeAndShape(data, type)
-% Validates data has the expected type and is a vector or empty 2D
-% matrix. If data is numeric, validates is real and nonsparse.
-
-    arguments
-        data
-        type(1, 1) string
-    end
-
-    % If data is empty, only require it's shape to be 2D to support 0x0 
-    % arrays. Otherwise, require data to be a vector.
-    %
-    % TODO: Consider supporting nonvector 2D arrays. We chould reshape them
-    % to column vectors if needed.
-    
-    expectedShape = "vector";
-    if isempty(data)
-        expectedShape = "2d";
-    end
-    validateattributes(data, type, [expectedShape, "nonsparse", "real"]);
-end
\ No newline at end of file
diff --git a/matlab/src/matlab/+arrow/+array/Array.m 
b/matlab/src/matlab/+arrow/+array/Array.m
index 7426052764..46b46660e7 100644
--- a/matlab/src/matlab/+arrow/+array/Array.m
+++ b/matlab/src/matlab/+arrow/+array/Array.m
@@ -31,8 +31,11 @@ classdef (Abstract) Array < matlab.mixin.CustomDisplay & ...
     end
     
     methods
-        function obj = Array(varargin)
-            obj.Proxy = libmexclass.proxy.Proxy(varargin{:}); 
+        function obj = Array(proxy)
+            arguments
+                proxy(1, 1) libmexclass.proxy.Proxy
+            end
+            obj.Proxy = proxy;
         end
 
         function numElements = get.Length(obj)
diff --git a/matlab/src/matlab/+arrow/+array/BooleanArray.m 
b/matlab/src/matlab/+arrow/+array/BooleanArray.m
index f4d341efce..b9ef36b5a7 100644
--- a/matlab/src/matlab/+arrow/+array/BooleanArray.m
+++ b/matlab/src/matlab/+arrow/+array/BooleanArray.m
@@ -21,16 +21,12 @@ classdef BooleanArray < arrow.array.Array
     end
 
     methods
-        function obj = BooleanArray(data, opts)
-            arguments
-                data
-                opts.InferNulls(1,1) logical = true
-                opts.Valid
+        function obj = BooleanArray(proxy)
+             arguments
+                proxy(1, 1) libmexclass.proxy.Proxy {validate(proxy, 
"arrow.array.proxy.BooleanArray")}
             end
-            arrow.args.validateTypeAndShape(data, "logical");
-            validElements = arrow.args.parseValidElements(data, opts);
-            opts = struct(MatlabArray=data, Valid=validElements);
-            [email protected]("Name", "arrow.array.proxy.BooleanArray", 
"ConstructorArguments", {opts});
+            import arrow.internal.proxy.validate
+            [email protected](proxy);
         end
 
         function data = logical(obj)
@@ -42,4 +38,23 @@ classdef BooleanArray < arrow.array.Array
             matlabArray(~obj.Valid) = obj.NullSubstitionValue;
         end
     end
+
+    methods (Static)
+        function array = fromMATLAB(data, opts)
+            arguments
+                data
+                opts.InferNulls(1, 1) logical = true
+                opts.Valid
+            end
+
+            arrow.internal.validate.type(data, "logical");
+            arrow.internal.validate.shape(data);
+            arrow.internal.validate.nonsparse(data);
+            validElements = arrow.internal.validate.parseValidElements(data, 
opts);
+            
+            args = struct(MatlabArray=data, Valid=validElements);
+            proxy = 
arrow.internal.proxy.create("arrow.array.proxy.BooleanArray", args);
+            array = arrow.array.BooleanArray(proxy);
+        end
+    end
 end
diff --git a/matlab/src/matlab/+arrow/+array/Float32Array.m 
b/matlab/src/matlab/+arrow/+array/Float32Array.m
index c6be563d86..fe90db335b 100644
--- a/matlab/src/matlab/+arrow/+array/Float32Array.m
+++ b/matlab/src/matlab/+arrow/+array/Float32Array.m
@@ -21,13 +21,23 @@ classdef Float32Array < arrow.array.NumericArray
     end
 
     methods
-        function obj = Float32Array(data, varargin)
-            [email protected](data, "single", ...
-                "arrow.array.proxy.Float32Array", varargin{:});
+        function obj = Float32Array(proxy)
+            arguments
+                proxy(1, 1) libmexclass.proxy.Proxy {validate(proxy, 
"arrow.array.proxy.Float32Array")}
+            end
+            import arrow.internal.proxy.validate
+            [email protected](proxy);
         end
 
         function data = single(obj)
             data = obj.toMATLAB();
         end
     end
+    
+    methods (Static)
+        function array = fromMATLAB(data, varargin)
+            traits = arrow.type.traits.Float32Traits;
+            array = arrow.array.NumericArray.fromMATLAB(data, traits, 
varargin{:});
+        end
+    end
 end
diff --git a/matlab/src/matlab/+arrow/+array/Float64Array.m 
b/matlab/src/matlab/+arrow/+array/Float64Array.m
index ff43ebc053..ecf91e2895 100644
--- a/matlab/src/matlab/+arrow/+array/Float64Array.m
+++ b/matlab/src/matlab/+arrow/+array/Float64Array.m
@@ -21,13 +21,23 @@ classdef Float64Array < arrow.array.NumericArray
     end
 
     methods
-        function obj = Float64Array(data, varargin)
-            [email protected](data, "double", ...
-                "arrow.array.proxy.Float64Array", varargin{:});
+        function obj = Float64Array(proxy)
+            arguments
+                proxy(1, 1) libmexclass.proxy.Proxy {validate(proxy, 
"arrow.array.proxy.Float64Array")}
+            end
+            import arrow.internal.proxy.validate
+            [email protected](proxy);
         end
 
         function data = double(obj)
             data = obj.toMATLAB();
         end
     end
+    
+    methods (Static)
+        function array = fromMATLAB(data, varargin)
+            traits = arrow.type.traits.Float64Traits;
+            array = arrow.array.NumericArray.fromMATLAB(data, traits, 
varargin{:});
+        end
+    end
 end
diff --git a/matlab/src/matlab/+arrow/+array/Int16Array.m 
b/matlab/src/matlab/+arrow/+array/Int16Array.m
index 533f0c9ef5..53c96c6eeb 100644
--- a/matlab/src/matlab/+arrow/+array/Int16Array.m
+++ b/matlab/src/matlab/+arrow/+array/Int16Array.m
@@ -21,13 +21,23 @@ classdef Int16Array < arrow.array.NumericArray
     end
 
     methods
-        function obj = Int16Array(data, varargin)
-            [email protected](data, "int16", ...
-                "arrow.array.proxy.Int16Array", varargin{:});
+        function obj = Int16Array(proxy)
+            arguments
+                proxy(1, 1) libmexclass.proxy.Proxy {validate(proxy, 
"arrow.array.proxy.Int16Array")}
+            end
+            import arrow.internal.proxy.validate
+            [email protected](proxy);
         end
 
         function data = int16(obj)
             data = obj.toMATLAB();
         end
     end
+
+    methods (Static)
+        function array = fromMATLAB(data, varargin)
+            traits = arrow.type.traits.Int16Traits;
+            array = arrow.array.NumericArray.fromMATLAB(data, traits, 
varargin{:});
+        end
+    end
 end
diff --git a/matlab/src/matlab/+arrow/+array/Int32Array.m 
b/matlab/src/matlab/+arrow/+array/Int32Array.m
index 0f977fb90f..d85bcaf627 100644
--- a/matlab/src/matlab/+arrow/+array/Int32Array.m
+++ b/matlab/src/matlab/+arrow/+array/Int32Array.m
@@ -21,13 +21,23 @@ classdef Int32Array < arrow.array.NumericArray
     end
 
     methods
-        function obj = Int32Array(data, varargin)
-              [email protected](data, "int32", ...
-                "arrow.array.proxy.Int32Array", varargin{:});
+        function obj = Int32Array(proxy)
+            arguments
+                proxy(1, 1) libmexclass.proxy.Proxy {validate(proxy, 
"arrow.array.proxy.Int32Array")}
+            end
+            import arrow.internal.proxy.validate
+            [email protected](proxy);
         end
 
         function data = int32(obj)
             data = obj.toMATLAB();
         end
     end
+
+    methods (Static)
+        function array = fromMATLAB(data, varargin)
+            traits = arrow.type.traits.Int32Traits;
+            array = arrow.array.NumericArray.fromMATLAB(data, traits, 
varargin{:});
+        end
+    end
 end
diff --git a/matlab/src/matlab/+arrow/+array/Int64Array.m 
b/matlab/src/matlab/+arrow/+array/Int64Array.m
index 94cad56519..72199df88d 100644
--- a/matlab/src/matlab/+arrow/+array/Int64Array.m
+++ b/matlab/src/matlab/+arrow/+array/Int64Array.m
@@ -21,13 +21,23 @@ classdef Int64Array < arrow.array.NumericArray
     end
 
     methods
-        function obj = Int64Array(data, varargin)
-          [email protected](data, "int64", ...
-                "arrow.array.proxy.Int64Array", varargin{:});
+        function obj = Int64Array(proxy)
+            arguments
+                proxy(1, 1) libmexclass.proxy.Proxy {validate(proxy, 
"arrow.array.proxy.Int64Array")}
+            end
+            import arrow.internal.proxy.validate
+            [email protected](proxy);
         end
 
         function data = int64(obj)
             data = obj.toMATLAB();
         end
     end
+
+    methods (Static)
+        function array = fromMATLAB(data, varargin)
+            traits = arrow.type.traits.Int64Traits;
+            array = arrow.array.NumericArray.fromMATLAB(data, traits, 
varargin{:});
+        end
+    end
 end
diff --git a/matlab/src/matlab/+arrow/+array/Int8Array.m 
b/matlab/src/matlab/+arrow/+array/Int8Array.m
index 83a14caa27..0e9d8eec0e 100644
--- a/matlab/src/matlab/+arrow/+array/Int8Array.m
+++ b/matlab/src/matlab/+arrow/+array/Int8Array.m
@@ -21,13 +21,23 @@ classdef Int8Array < arrow.array.NumericArray
     end
 
     methods
-        function obj = Int8Array(data, varargin)
-             [email protected](data, "int8", ...
-                "arrow.array.proxy.Int8Array", varargin{:});
+        function obj = Int8Array(proxy)
+            arguments
+                proxy(1, 1) libmexclass.proxy.Proxy {validate(proxy, 
"arrow.array.proxy.Int8Array")}
+            end
+            import arrow.internal.proxy.validate
+            [email protected](proxy);
         end
 
         function data = int8(obj)
             data = obj.toMATLAB();
         end
     end
+
+    methods (Static)
+        function array = fromMATLAB(data, varargin)
+            traits = arrow.type.traits.Int8Traits;
+            array = arrow.array.NumericArray.fromMATLAB(data, traits, 
varargin{:});
+        end
+    end
 end
diff --git a/matlab/src/matlab/+arrow/+array/NumericArray.m 
b/matlab/src/matlab/+arrow/+array/NumericArray.m
index fb2fc1d333..8f465ce425 100644
--- a/matlab/src/matlab/+arrow/+array/NumericArray.m
+++ b/matlab/src/matlab/+arrow/+array/NumericArray.m
@@ -21,18 +21,11 @@ classdef NumericArray < arrow.array.Array
     end
 
     methods
-        function obj = NumericArray(data, type, proxyName, opts)
+        function obj = NumericArray(proxy)
             arguments
-                data
-                type(1, 1) string
-                proxyName(1, 1) string
-                opts.InferNulls(1, 1) logical = true
-                opts.Valid
+                proxy(1, 1) libmexclass.proxy.Proxy
             end
-            arrow.args.validateTypeAndShape(data, type);
-            validElements = arrow.args.parseValidElements(data, opts);
-            opts = struct(MatlabArray=data, Valid=validElements);
-            [email protected]("Name", proxyName, "ConstructorArguments", 
{opts});
+            [email protected](proxy);
         end
 
         function matlabArray = toMATLAB(obj)
@@ -40,5 +33,22 @@ classdef NumericArray < arrow.array.Array
             matlabArray(~obj.Valid) = obj.NullSubstitutionValue;
         end
     end
+
+    methods (Static)
+        function array = fromMATLAB(data, traits, opts)
+            arguments
+                data
+                traits(1, 1) arrow.type.traits.TypeTraits
+                opts.InferNulls(1, 1) logical = true
+                opts.Valid
+            end
+
+            arrow.internal.validate.numeric(data, traits.MatlabClassName);
+            validElements = arrow.internal.validate.parseValidElements(data, 
opts);
+            args = struct(MatlabArray=data, Valid=validElements);
+            proxy = arrow.internal.proxy.create(traits.ArrayProxyClassName, 
args);
+            array = traits.ArrayConstructor(proxy);
+        end
+    end
 end
 
diff --git a/matlab/src/matlab/+arrow/+array/StringArray.m 
b/matlab/src/matlab/+arrow/+array/StringArray.m
index ec2d53b371..18fdec9ac7 100644
--- a/matlab/src/matlab/+arrow/+array/StringArray.m
+++ b/matlab/src/matlab/+arrow/+array/StringArray.m
@@ -21,21 +21,12 @@ classdef StringArray < arrow.array.Array
     end
 
     methods
-        function obj = StringArray(data, opts)
-            arguments
-                data
-                opts.InferNulls(1,1) logical = true
-                opts.Valid
+        function obj = StringArray(proxy)
+         arguments
+                proxy(1, 1) libmexclass.proxy.Proxy {validate(proxy, 
"arrow.array.proxy.StringArray")}
             end
-            % Support constructing a StringArray from a cell array of strings 
(i.e. cellstr),
-            % or a string array, but not a char array.
-            if ~ischar(data)
-                data = convertCharsToStrings(data);
-            end
-            arrow.args.validateTypeAndShape(data, "string");
-            validElements = arrow.args.parseValidElements(data, opts);
-            opts = struct(MatlabArray=data, Valid=validElements);
-            [email protected]("Name", "arrow.array.proxy.StringArray", 
"ConstructorArguments", {opts});
+            import arrow.internal.proxy.validate
+            [email protected](proxy);
         end
 
         function data = string(obj)
@@ -47,4 +38,28 @@ classdef StringArray < arrow.array.Array
             matlabArray(~obj.Valid) = obj.NullSubstitionValue;
         end
     end
+
+    methods (Static)
+        function array = fromMATLAB(data, opts)
+            arguments
+                data
+                opts.InferNulls(1, 1) logical = true
+                opts.Valid
+            end
+            
+            % Support constructing a StringArray from a cell array of strings
+            % (i.e. cellstr), or a string array, but not a char array.
+            if ~ischar(data)
+                data = convertCharsToStrings(data);
+            end
+
+            arrow.internal.validate.type(data, "string");
+            arrow.internal.validate.shape(data);
+            validElements = arrow.internal.validate.parseValidElements(data, 
opts);
+            
+            args = struct(MatlabArray=data, Valid=validElements);
+            proxy = 
arrow.internal.proxy.create("arrow.array.proxy.StringArray", args);
+            array = arrow.array.StringArray(proxy);
+        end
+    end
 end
diff --git a/matlab/src/matlab/+arrow/+array/TimestampArray.m 
b/matlab/src/matlab/+arrow/+array/TimestampArray.m
index 0f0da4e821..3b05903bb1 100644
--- a/matlab/src/matlab/+arrow/+array/TimestampArray.m
+++ b/matlab/src/matlab/+arrow/+array/TimestampArray.m
@@ -21,20 +21,12 @@ classdef TimestampArray < arrow.array.Array
     end
 
     methods
-        function obj = TimestampArray(data, opts)
+        function obj = TimestampArray(proxy)
             arguments
-                data
-                opts.TimeUnit(1, 1) arrow.type.TimeUnit = 
arrow.type.TimeUnit.Microsecond
-                opts.InferNulls(1, 1) logical = true
-                opts.Valid
+                proxy(1, 1) libmexclass.proxy.Proxy {validate(proxy, 
"arrow.array.proxy.TimestampArray")}
             end
-            arrow.args.validateTypeAndShape(data, "datetime");
-            validElements = arrow.args.parseValidElements(data, opts);
-            ptime = arrow.array.TimestampArray.convertToEpochTime(data, 
opts.TimeUnit);
-            timezone = string(data.TimeZone);
-
-            args = struct(MatlabArray=ptime, Valid=validElements, 
TimeZone=timezone, TimeUnit=string(opts.TimeUnit));
-            [email protected]("Name", "arrow.array.proxy.TimestampArray", 
"ConstructorArguments", {args});
+            import arrow.internal.proxy.validate
+            [email protected](proxy);
         end
 
         function dates = toMATLAB(obj)
@@ -70,4 +62,26 @@ classdef TimestampArray < arrow.array.Array
             time(indices) = convertTo(dates(indices), "epochtime", 
TicksPerSecond=ticksPerSecond(units));
         end
     end
+
+    methods(Static)
+        function array = fromMATLAB(data, opts)
+            arguments
+                data
+                opts.TimeUnit(1, 1) arrow.type.TimeUnit = 
arrow.type.TimeUnit.Microsecond
+                opts.InferNulls(1, 1) logical = true
+                opts.Valid
+            end
+            
+            arrow.internal.validate.type(data, "datetime");
+            arrow.internal.validate.shape(data);
+
+            validElements = arrow.internal.validate.parseValidElements(data, 
opts);
+            epochTime = arrow.array.TimestampArray.convertToEpochTime(data, 
opts.TimeUnit);
+            timezone = string(data.TimeZone);
+
+            args = struct(MatlabArray=epochTime, Valid=validElements, 
TimeZone=timezone, TimeUnit=string(opts.TimeUnit));
+            proxy = 
arrow.internal.proxy.create("arrow.array.proxy.TimestampArray", args);
+            array = arrow.array.TimestampArray(proxy);
+        end
+    end
 end
\ No newline at end of file
diff --git a/matlab/src/matlab/+arrow/+array/UInt16Array.m 
b/matlab/src/matlab/+arrow/+array/UInt16Array.m
index 4862ca20b9..9d3f33c279 100644
--- a/matlab/src/matlab/+arrow/+array/UInt16Array.m
+++ b/matlab/src/matlab/+arrow/+array/UInt16Array.m
@@ -21,13 +21,23 @@ classdef UInt16Array < arrow.array.NumericArray
     end
 
     methods
-        function obj = UInt16Array(data, varargin)
-            [email protected](data, "uint16", ...
-                "arrow.array.proxy.UInt16Array", varargin{:});
+        function obj = UInt16Array(proxy)
+            arguments
+                proxy(1, 1) libmexclass.proxy.Proxy {validate(proxy, 
"arrow.array.proxy.UInt16Array")}
+            end
+            import arrow.internal.proxy.validate
+            [email protected](proxy);
         end
 
         function data = uint16(obj)
             data = obj.toMATLAB();
         end
     end
+
+    methods (Static)
+        function array = fromMATLAB(data, varargin)
+            traits = arrow.type.traits.UInt16Traits;
+            array = arrow.array.NumericArray.fromMATLAB(data, traits, 
varargin{:});
+        end
+    end
 end
diff --git a/matlab/src/matlab/+arrow/+array/UInt32Array.m 
b/matlab/src/matlab/+arrow/+array/UInt32Array.m
index 782b001099..5235d4fb15 100644
--- a/matlab/src/matlab/+arrow/+array/UInt32Array.m
+++ b/matlab/src/matlab/+arrow/+array/UInt32Array.m
@@ -21,13 +21,23 @@ classdef UInt32Array < arrow.array.NumericArray
     end
 
     methods
-        function obj = UInt32Array(data, varargin)
-            [email protected](data, "uint32", ...
-                "arrow.array.proxy.UInt32Array", varargin{:});
+        function obj = UInt32Array(proxy)
+            arguments
+                proxy(1, 1) libmexclass.proxy.Proxy {validate(proxy, 
"arrow.array.proxy.UInt32Array")}
+            end
+            import arrow.internal.proxy.validate
+            [email protected](proxy);
         end
 
         function data = uint32(obj)
             data = obj.toMATLAB();
         end
     end
+
+    methods (Static)
+        function array = fromMATLAB(data, varargin)
+            traits = arrow.type.traits.UInt32Traits;
+            array = arrow.array.NumericArray.fromMATLAB(data, traits, 
varargin{:});
+        end
+    end
 end
diff --git a/matlab/src/matlab/+arrow/+array/UInt64Array.m 
b/matlab/src/matlab/+arrow/+array/UInt64Array.m
index 9e25ce4987..2d69bd031a 100644
--- a/matlab/src/matlab/+arrow/+array/UInt64Array.m
+++ b/matlab/src/matlab/+arrow/+array/UInt64Array.m
@@ -21,13 +21,23 @@ classdef UInt64Array < arrow.array.NumericArray
     end
 
     methods
-        function obj = UInt64Array(data, varargin)
-            [email protected](data, "uint64", ...
-                "arrow.array.proxy.UInt64Array", varargin{:});
+        function obj = UInt64Array(proxy)
+            arguments
+                proxy(1, 1) libmexclass.proxy.Proxy {validate(proxy, 
"arrow.array.proxy.UInt64Array")}
+            end
+            import arrow.internal.proxy.validate
+            [email protected](proxy);
         end
 
         function data = uint64(obj)
             data = obj.toMATLAB();
         end
     end
+
+    methods (Static)
+        function array = fromMATLAB(data, varargin)
+            traits = arrow.type.traits.UInt64Traits;
+            array = arrow.array.NumericArray.fromMATLAB(data, traits, 
varargin{:});
+        end
+    end
 end
diff --git a/matlab/src/matlab/+arrow/+array/UInt8Array.m 
b/matlab/src/matlab/+arrow/+array/UInt8Array.m
index 8bad2401bd..3d007376bc 100644
--- a/matlab/src/matlab/+arrow/+array/UInt8Array.m
+++ b/matlab/src/matlab/+arrow/+array/UInt8Array.m
@@ -21,13 +21,23 @@ classdef UInt8Array < arrow.array.NumericArray
     end
 
     methods
-        function obj = UInt8Array(data, varargin)
-            [email protected](data, "uint8", ...
-                "arrow.array.proxy.UInt8Array", varargin{:});
+        function obj = UInt8Array(proxy)
+          arguments
+                proxy(1, 1) libmexclass.proxy.Proxy {validate(proxy, 
"arrow.array.proxy.UInt8Array")}
+            end
+            import arrow.internal.proxy.validate
+            [email protected](proxy);
         end
 
         function data = uint8(obj)
             data = obj.toMATLAB();
         end
     end
+
+        methods (Static)
+        function array = fromMATLAB(data, varargin)
+            traits = arrow.type.traits.UInt8Traits;
+            array = arrow.array.NumericArray.fromMATLAB(data, traits, 
varargin{:});
+        end
+    end
 end
diff --git a/matlab/src/matlab/+arrow/+array/Int8Array.m 
b/matlab/src/matlab/+arrow/+internal/+validate/nonsparse.m
similarity index 64%
copy from matlab/src/matlab/+arrow/+array/Int8Array.m
copy to matlab/src/matlab/+arrow/+internal/+validate/nonsparse.m
index 83a14caa27..8f7557c18b 100644
--- a/matlab/src/matlab/+arrow/+array/Int8Array.m
+++ b/matlab/src/matlab/+arrow/+internal/+validate/nonsparse.m
@@ -1,3 +1,6 @@
+%NONSPARESE Verifies data is nonsparse. Otherwise throws an error with the 
+% identifier "arrrow:array:Sparse".
+
 % Licensed to the Apache Software Foundation (ASF) under one or more
 % contributor license agreements.  See the NOTICE file distributed with
 % this work for additional information regarding copyright ownership.
@@ -13,21 +16,10 @@
 % implied.  See the License for the specific language governing
 % permissions and limitations under the License.
 
-classdef Int8Array < arrow.array.NumericArray
-% arrow.array.Int8Array
-
-    properties (Access=protected)
-        NullSubstitutionValue = int8(0);
-    end
-
-    methods
-        function obj = Int8Array(data, varargin)
-             [email protected](data, "int8", ...
-                "arrow.array.proxy.Int8Array", varargin{:});
-        end
-
-        function data = int8(obj)
-            data = obj.toMATLAB();
-        end
+function nonsparse(data)
+    if issparse(data)
+        errid = "arrow:array:Sparse";
+        msg = "Sparse arrays are not supported.";
+        error(errid, msg);
     end
 end
diff --git a/matlab/src/matlab/+arrow/+array/Int8Array.m 
b/matlab/src/matlab/+arrow/+internal/+validate/numeric.m
similarity index 64%
copy from matlab/src/matlab/+arrow/+array/Int8Array.m
copy to matlab/src/matlab/+arrow/+internal/+validate/numeric.m
index 83a14caa27..9dfe6dfada 100644
--- a/matlab/src/matlab/+arrow/+array/Int8Array.m
+++ b/matlab/src/matlab/+arrow/+internal/+validate/numeric.m
@@ -1,3 +1,6 @@
+%NUMERIC Validates data is a real, nonsparse, numeric array that is
+%either a vector or an empty array.
+
 % Licensed to the Apache Software Foundation (ASF) under one or more
 % contributor license agreements.  See the NOTICE file distributed with
 % this work for additional information regarding copyright ownership.
@@ -12,22 +15,10 @@
 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 % implied.  See the License for the specific language governing
 % permissions and limitations under the License.
-
-classdef Int8Array < arrow.array.NumericArray
-% arrow.array.Int8Array
-
-    properties (Access=protected)
-        NullSubstitutionValue = int8(0);
-    end
-
-    methods
-        function obj = Int8Array(data, varargin)
-             [email protected](data, "int8", ...
-                "arrow.array.proxy.Int8Array", varargin{:});
-        end
-
-        function data = int8(obj)
-            data = obj.toMATLAB();
-        end
-    end
+function numeric(data, type)
+    arrow.internal.validate.type(data, type);
+    arrow.internal.validate.shape(data);
+    arrow.internal.validate.nonsparse(data);
+    arrow.internal.validate.realnumeric(data);
 end
+
diff --git a/matlab/src/matlab/+arrow/+args/parseValidElements.m 
b/matlab/src/matlab/+arrow/+internal/+validate/parseValidElements.m
similarity index 100%
rename from matlab/src/matlab/+arrow/+args/parseValidElements.m
rename to matlab/src/matlab/+arrow/+internal/+validate/parseValidElements.m
diff --git a/matlab/src/matlab/+arrow/+array/Int8Array.m 
b/matlab/src/matlab/+arrow/+internal/+validate/realnumeric.m
similarity index 64%
copy from matlab/src/matlab/+arrow/+array/Int8Array.m
copy to matlab/src/matlab/+arrow/+internal/+validate/realnumeric.m
index 83a14caa27..1f57cee4d8 100644
--- a/matlab/src/matlab/+arrow/+array/Int8Array.m
+++ b/matlab/src/matlab/+arrow/+internal/+validate/realnumeric.m
@@ -1,3 +1,6 @@
+%REALNUMERIC Verifies the numeric array data is real. Otherwise throws an 
+% error with the identifier "arrrow:array:ComplexNumeric".
+
 % Licensed to the Apache Software Foundation (ASF) under one or more
 % contributor license agreements.  See the NOTICE file distributed with
 % this work for additional information regarding copyright ownership.
@@ -13,21 +16,10 @@
 % implied.  See the License for the specific language governing
 % permissions and limitations under the License.
 
-classdef Int8Array < arrow.array.NumericArray
-% arrow.array.Int8Array
-
-    properties (Access=protected)
-        NullSubstitutionValue = int8(0);
-    end
-
-    methods
-        function obj = Int8Array(data, varargin)
-             [email protected](data, "int8", ...
-                "arrow.array.proxy.Int8Array", varargin{:});
-        end
-
-        function data = int8(obj)
-            data = obj.toMATLAB();
-        end
+function realnumeric(data)
+    if ~isreal(data)
+        errid = "arrow:array:ComplexNumeric";
+        msg = "Complex numeric arrays are not supported.";
+        error(errid, msg);
     end
 end
diff --git a/matlab/src/matlab/+arrow/+array/Int8Array.m 
b/matlab/src/matlab/+arrow/+internal/+validate/shape.m
similarity index 64%
copy from matlab/src/matlab/+arrow/+array/Int8Array.m
copy to matlab/src/matlab/+arrow/+internal/+validate/shape.m
index 83a14caa27..d9a8e29076 100644
--- a/matlab/src/matlab/+arrow/+array/Int8Array.m
+++ b/matlab/src/matlab/+arrow/+internal/+validate/shape.m
@@ -1,3 +1,6 @@
+%SHAPE Verifies data is either a vector or empty. Otherwise throws an error
+% with the identifier "arrrow:array:InvalidShape".
+
 % Licensed to the Apache Software Foundation (ASF) under one or more
 % contributor license agreements.  See the NOTICE file distributed with
 % this work for additional information regarding copyright ownership.
@@ -13,21 +16,11 @@
 % implied.  See the License for the specific language governing
 % permissions and limitations under the License.
 
-classdef Int8Array < arrow.array.NumericArray
-% arrow.array.Int8Array
-
-    properties (Access=protected)
-        NullSubstitutionValue = int8(0);
-    end
-
-    methods
-        function obj = Int8Array(data, varargin)
-             [email protected](data, "int8", ...
-                "arrow.array.proxy.Int8Array", varargin{:});
-        end
-
-        function data = int8(obj)
-            data = obj.toMATLAB();
-        end
+function shape(data)
+    if ~isvector(data) && ~isempty(data)
+        errid = "arrow:array:InvalidShape";
+        msg = "Expected input array to be a vector or empty.";
+        error(errid, msg);
     end
 end
+
diff --git a/matlab/src/matlab/+arrow/+array/Int8Array.m 
b/matlab/src/matlab/+arrow/+internal/+validate/type.m
similarity index 64%
copy from matlab/src/matlab/+arrow/+array/Int8Array.m
copy to matlab/src/matlab/+arrow/+internal/+validate/type.m
index 83a14caa27..7977d812ad 100644
--- a/matlab/src/matlab/+arrow/+array/Int8Array.m
+++ b/matlab/src/matlab/+arrow/+internal/+validate/type.m
@@ -1,3 +1,6 @@
+%TYPE Verifies data has the expected class type. Otherwise throws an 
+% error with the identifier "arrrow:array:InvalidType".
+
 % Licensed to the Apache Software Foundation (ASF) under one or more
 % contributor license agreements.  See the NOTICE file distributed with
 % this work for additional information regarding copyright ownership.
@@ -13,21 +16,10 @@
 % implied.  See the License for the specific language governing
 % permissions and limitations under the License.
 
-classdef Int8Array < arrow.array.NumericArray
-% arrow.array.Int8Array
-
-    properties (Access=protected)
-        NullSubstitutionValue = int8(0);
-    end
-
-    methods
-        function obj = Int8Array(data, varargin)
-             [email protected](data, "int8", ...
-                "arrow.array.proxy.Int8Array", varargin{:});
-        end
-
-        function data = int8(obj)
-            data = obj.toMATLAB();
-        end
+function type(data, classtype)
+    if ~isa(data, classtype)
+        errid = "arrow:array:InvalidType";
+        msg = join(["Expected data to be a", classtype, "array"]);
+        error(errid, msg);
     end
 end
diff --git a/matlab/src/matlab/+arrow/+tabular/RecordBatch.m 
b/matlab/src/matlab/+arrow/+tabular/RecordBatch.m
index a7feb0c0a3..9af09702e1 100644
--- a/matlab/src/matlab/+arrow/+tabular/RecordBatch.m
+++ b/matlab/src/matlab/+arrow/+tabular/RecordBatch.m
@@ -89,49 +89,10 @@ classdef RecordBatch < matlab.mixin.CustomDisplay & ...
             % Convert each MATLAB array into a corresponding
             % arrow.array.Array.
             for ii = 1:numColumns
-                arrowArrays{ii} = arrow.tabular.RecordBatch.makeArray(T{:, 
ii});
+                arrowArrays{ii} = arrow.array(T{:, ii});
             end
         end
 
-        function arrowArray = makeArray(matlabArray)
-            % Decompose the input MATLAB table
-            % input a cell array of equivalent arrow.array.Array
-            % instances.
-
-            switch class(matlabArray)
-                case "single"
-                    arrowArray = arrow.array.Float32Array(matlabArray);
-                case "double"
-                    arrowArray = arrow.array.Float64Array(matlabArray);
-                case "uint8"
-                    arrowArray = arrow.array.UInt8Array(matlabArray);
-                case "uint16"
-                    arrowArray = arrow.array.UInt16Array(matlabArray);
-                case "uint32"
-                    arrowArray = arrow.array.UInt32Array(matlabArray);
-                case "uint64"
-                    arrowArray = arrow.array.UInt64Array(matlabArray);
-                case "int8"
-                    arrowArray = arrow.array.Int8Array(matlabArray);
-                case "int16"
-                    arrowArray = arrow.array.Int16Array(matlabArray);
-                case "int32"
-                    arrowArray = arrow.array.Int32Array(matlabArray);
-                case "int64"
-                    arrowArray = arrow.array.Int64Array(matlabArray);
-                case "logical"
-                    arrowArray = arrow.array.BooleanArray(matlabArray);
-                case "string"
-                    arrowArray = arrow.array.StringArray(matlabArray);
-                case "datetime"
-                    arrowArray = arrow.array.TimestampArray(matlabArray);
-                otherwise
-                    
error("arrow:tabular:recordbatch:UnsupportedMatlabArrayType", ...
-                          "RecordBatch cannot be constructed from a MATLAB 
array of type '" + class(matlabArray) + "'.");
-            end
-
-        end
-
         function proxyIDs = getArrowProxyIDs(arrowArrays)
             % Extract the Proxy IDs underlying a cell array of 
             % arrow.array.Array instances.
diff --git a/matlab/src/matlab/+arrow/array.m b/matlab/src/matlab/+arrow/array.m
new file mode 100644
index 0000000000..a2d0ecd2e8
--- /dev/null
+++ b/matlab/src/matlab/+arrow/array.m
@@ -0,0 +1,67 @@
+% Licensed to the Apache Software Foundation (ASF) under one or more
+% contributor license agreements.  See the NOTICE file distributed with
+% this work for additional information regarding copyright ownership.
+% The ASF licenses this file to you under the Apache License, Version
+% 2.0 (the "License"); you may not use this file except in compliance
+% with the License.  You may obtain a copy of the License at
+%
+%   http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS,
+% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+% implied.  See the License for the specific language governing
+% permissions and limitations under the License.
+
+function arrowArray = array(data, opts)
+    arguments
+        data
+        opts.InferNulls(1, 1) logical = true
+        opts.Valid
+    end
+
+    data = convertCellstrToString(data);
+    classname = string(class(data));
+    args = namedargs2cell(opts);
+
+    switch (classname)
+        case "logical"
+            arrowArray = arrow.array.BooleanArray.fromMATLAB(data, args{:});
+        case "uint8"
+            arrowArray = arrow.array.UInt8Array.fromMATLAB(data, args{:});
+        case "uint16"
+            arrowArray = arrow.array.UInt16Array.fromMATLAB(data, args{:});
+        case "uint32"
+            arrowArray = arrow.array.UInt32Array.fromMATLAB(data, args{:});
+        case "uint64"
+            arrowArray = arrow.array.UInt64Array.fromMATLAB(data, args{:});
+        case "int8"
+            arrowArray = arrow.array.Int8Array.fromMATLAB(data, args{:});
+        case "int16"
+            arrowArray = arrow.array.Int16Array.fromMATLAB(data, args{:});
+        case "int32"
+            arrowArray = arrow.array.Int32Array.fromMATLAB(data, args{:});
+        case "int64"
+            arrowArray = arrow.array.Int64Array.fromMATLAB(data, args{:});
+        case "single"
+            arrowArray = arrow.array.Float32Array.fromMATLAB(data, args{:});
+        case "double"
+            arrowArray = arrow.array.Float64Array.fromMATLAB(data, args{:});
+        case "string"
+            arrowArray = arrow.array.StringArray.fromMATLAB(data, args{:});
+        case "datetime"
+            arrowArray = arrow.array.TimestampArray.fromMATLAB(data, args{:});
+        otherwise
+            errid = "arrow:array:UnsupportedMATLABType";
+            msg = join(["Unable to convert MATLAB type" classname "to arrow 
array."]);
+            error(errid, msg);
+    end
+end
+
+function data = convertCellstrToString(data)
+    % Support constructing a StringArray from a cell array of strings
+    % (i.e. cellstr), or a string array, but not a char array.
+    if ~ischar(data)
+        data = convertCharsToStrings(data);
+    end
+end
\ No newline at end of file
diff --git a/matlab/test/arrow/array/hNumericArray.m 
b/matlab/test/arrow/array/hNumericArray.m
index f9f5f1d9e4..fc5f5a0599 100644
--- a/matlab/test/arrow/array/hNumericArray.m
+++ b/matlab/test/arrow/array/hNumericArray.m
@@ -18,7 +18,7 @@ classdef hNumericArray < matlab.unittest.TestCase
 
     properties (Abstract)
         ArrowArrayClassName(1, 1) string
-        ArrowArrayConstructor
+        ArrowArrayConstructorFcn
         MatlabArrayFcn
         MatlabConversionFcn
         MaxValue (1, 1)
@@ -38,24 +38,24 @@ classdef hNumericArray < matlab.unittest.TestCase
 
     methods(Test)
         function BasicTest(tc)
-            A = tc.ArrowArrayConstructor(tc.MatlabArrayFcn([1 2 3]));
+            A = tc.ArrowArrayConstructorFcn(tc.MatlabArrayFcn([1 2 3]));
             className = string(class(A));
             tc.verifyEqual(className, tc.ArrowArrayClassName);
         end
 
         function ToMATLAB(tc)
             % Create array from a scalar
-            A1 = tc.ArrowArrayConstructor(tc.MatlabArrayFcn(100));
+            A1 = tc.ArrowArrayConstructorFcn(tc.MatlabArrayFcn(100));
             data = toMATLAB(A1);
             tc.verifyEqual(data, tc.MatlabArrayFcn(100));
 
             % Create array from a vector
-            A2 = tc.ArrowArrayConstructor(tc.MatlabArrayFcn([1 2 3]));
+            A2 = tc.ArrowArrayConstructorFcn(tc.MatlabArrayFcn([1 2 3]));
             data = toMATLAB(A2);
             tc.verifyEqual(data, tc.MatlabArrayFcn([1 2 3]'));
 
             % Create a Float64Array from an empty double vector
-            A3 = tc.ArrowArrayConstructor(tc.MatlabArrayFcn([]));
+            A3 = tc.ArrowArrayConstructorFcn(tc.MatlabArrayFcn([]));
             data = toMATLAB(A3);
             tc.verifyEqual(data, tc.MatlabArrayFcn(reshape([], 0, 1)));
         end
@@ -65,54 +65,55 @@ classdef hNumericArray < matlab.unittest.TestCase
         % arrow.array.Float32Array, double for array.array.Float64Array
 
             % Create array from a scalar
-            A1 = tc.ArrowArrayConstructor(tc.MatlabArrayFcn(100));
+            A1 = tc.ArrowArrayConstructorFcn(tc.MatlabArrayFcn(100));
             data = tc.MatlabConversionFcn(A1);
             tc.verifyEqual(data, tc.MatlabArrayFcn(100));
 
             % Create array from a vector
-            A2 = tc.ArrowArrayConstructor(tc.MatlabArrayFcn([1 2 3]));
+            A2 = tc.ArrowArrayConstructorFcn(tc.MatlabArrayFcn([1 2 3]));
             data = tc.MatlabConversionFcn(A2);
             tc.verifyEqual(data, tc.MatlabArrayFcn([1 2 3]'));
 
             % Create an array from an empty vector
-            A3 = tc.ArrowArrayConstructor(tc.MatlabArrayFcn([]));
+            A3 = tc.ArrowArrayConstructorFcn(tc.MatlabArrayFcn([]));
             data = tc.MatlabConversionFcn(A3);
             tc.verifyEqual(data, tc.MatlabArrayFcn(reshape([], 0, 1)));
         end
 
         function MinValueTest(tc)
-            A = tc.ArrowArrayConstructor(tc.MinValue);
+            A = tc.ArrowArrayConstructorFcn(tc.MinValue);
             tc.verifyEqual(toMATLAB(A), tc.MinValue);
         end
 
         function MaxValueTest(tc)
-            A1 = tc.ArrowArrayConstructor(tc.MaxValue);
+            A1 = tc.ArrowArrayConstructorFcn(tc.MaxValue);
             tc.verifyEqual(toMATLAB(A1), tc.MaxValue);
         end
 
         function ErrorIfComplex(tc)
-            fcn = @() tc.ArrowArrayConstructor(tc.MatlabArrayFcn([10 + 1i, 
4]));
-            tc.verifyError(fcn, "MATLAB:expectedReal");
+            fcn = @() tc.ArrowArrayConstructorFcn(tc.MatlabArrayFcn([10 + 1i, 
4]));
+            tc.verifyError(fcn, "arrow:array:ComplexNumeric");
         end
 
         function ErrorIfNonVector(tc)
             data = tc.MatlabArrayFcn([1 2 3 4 5 6 7 8 9]);
             data = reshape(data, 3, 1, 3);
-            fcn = @() tc.ArrowArrayConstructor(tc.MatlabArrayFcn(data));
-            tc.verifyError(fcn, "MATLAB:expectedVector");
+            fcn = @() tc.ArrowArrayConstructorFcn(tc.MatlabArrayFcn(data));
+            tc.verifyError(fcn, "arrow:array:InvalidShape");
         end
 
-        function ErrorIfEmptyArrayIsNotTwoDimensional(tc)
+        function AllowNDimensionalEmptyArray(tc)
             data = tc.MatlabArrayFcn(reshape([], [1 0 0]));
-            fcn = @() tc.ArrowArrayConstructor(data);
-            tc.verifyError(fcn, "MATLAB:expected2D");
+            A = tc.ArrowArrayConstructorFcn(data);
+            tc.verifyEqual(A.Length, int64(0));
+            tc.verifyEqual(toMATLAB(A), tc.MatlabArrayFcn(reshape([], [0 1])));
         end
 
         function LogicalValidNVPair(tc)
             % Verify the expected elements are treated as null when Valid
             % is provided as a logical array
             data = tc.MatlabArrayFcn([1 2 3 4]);
-            arrowArray = tc.ArrowArrayConstructor(data, Valid=[false true true 
false]);
+            arrowArray = tc.ArrowArrayConstructorFcn(data, Valid=[false true 
true false]);
         
             expectedData = data';
             expectedData([1 4]) = tc.NullSubstitutionValue;
@@ -125,7 +126,7 @@ classdef hNumericArray < matlab.unittest.TestCase
             % Verify the expected elements are treated as null when Valid
             % is provided as a array of indices
             data = tc.MatlabArrayFcn([1 2 3 4]);
-            arrowArray = tc.ArrowArrayConstructor(data, Valid=[2 4]);
+            arrowArray = tc.ArrowArrayConstructorFcn(data, Valid=[2 4]);
         
             expectedData = data';
             expectedData([1 3]) = tc.NullSubstitutionValue;
@@ -136,7 +137,7 @@ classdef hNumericArray < matlab.unittest.TestCase
             % Make sure the optimization where the valid-bitmap is stored
             % as a nullptr works as expected.
             expectedData = data';
-            arrowArray = tc.ArrowArrayConstructor(data, Valid=[1, 2, 3, 4]);
+            arrowArray = tc.ArrowArrayConstructorFcn(data, Valid=[1, 2, 3, 4]);
             tc.verifyEqual(tc.MatlabConversionFcn(arrowArray), expectedData);
             tc.verifyEqual(toMATLAB(arrowArray), expectedData);
             tc.verifyEqual(arrowArray.Valid, [true; true; true; true]);
@@ -145,7 +146,7 @@ classdef hNumericArray < matlab.unittest.TestCase
         function TestArrowType(tc)
         % Verify the array has the expected arrow.type.Type object
             data = tc.MatlabArrayFcn([1 2 3 4]);
-            arrowArray = tc.ArrowArrayConstructor(data);
+            arrowArray = tc.ArrowArrayConstructorFcn(data);
             tc.verifyEqual(arrowArray.Type.ID, tc.ArrowType.ID);
         end
     end
diff --git a/matlab/test/arrow/array/tArray.m b/matlab/test/arrow/array/tArray.m
new file mode 100644
index 0000000000..4a476696bf
--- /dev/null
+++ b/matlab/test/arrow/array/tArray.m
@@ -0,0 +1,88 @@
+%TARRAY Unit tests for arrow.array function. 
+
+% Licensed to the Apache Software Foundation (ASF) under one or more
+% contributor license agreements.  See the NOTICE file distributed with
+% this work for additional information regarding copyright ownership.
+% The ASF licenses this file to you under the Apache License, Version
+% 2.0 (the "License"); you may not use this file except in compliance
+% with the License.  You may obtain a copy of the License at
+%
+%   http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS,
+% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+% implied.  See the License for the specific language governing
+% permissions and limitations under the License.
+
+classdef tArray < matlab.unittest.TestCase
+
+    properties(TestParameter)
+        MATLABDataArrayTypePair = { ...
+            {[true false],         "arrow.array.BooleanArray"}, ...
+            {int8([1 2]),          "arrow.array.Int8Array"}, ...
+            {uint8([1 2]),         "arrow.array.UInt8Array"}, ...
+            {int16([1 2]),         "arrow.array.Int16Array"}, ...
+            {uint16([1 2]),        "arrow.array.UInt16Array"}, ...
+            {int32([1 2]),         "arrow.array.Int32Array"}, ...
+            {uint32([1 2]),        "arrow.array.UInt32Array"}, ...
+            {int64([1 2]),         "arrow.array.Int64Array"}, ...
+            {uint64([1 2]),        "arrow.array.UInt64Array"}, ...
+            {single([1 2]),        "arrow.array.Float32Array"}, ...
+            {[1 2],                "arrow.array.Float64Array"}, ...
+            {datetime(2022, 1, 1), "arrow.array.TimestampArray"}, ...
+            {["A" "B"],            "arrow.array.StringArray"}};
+    end
+
+    methods(Test)        
+        function ArrowArrayOutputType(testCase, MATLABDataArrayTypePair)
+        % Verify arrow.array returns the expected arrow.array.<Type>Array
+        % with respect to the input data array's MATLAB class type.
+            matlabArray = MATLABDataArrayTypePair{1};
+            expectedClassName = MATLABDataArrayTypePair{2};
+            arrowArray = arrow.array(matlabArray);
+            actualClassName = string(class(arrowArray));
+            testCase.verifyEqual(actualClassName, expectedClassName);
+        end
+
+        function UnsupportedMATLABTypeError(testCase)
+        % Verify arrow.array throws an error with the identifier
+        % "arrow:array:UnsupportedMATLABType" if the input array is not one
+        % we support converting into an Arrow array.
+            matlabArray = table;
+            fcn = @() arrow.array(matlabArray);
+            errID = "arrow:array:UnsupportedMATLABType";
+            testCase.verifyError(fcn, errID);
+        end
+
+        function InferNullsDefault(testCase)
+        % Verify InferNulls is true by default.
+            matlabArray = [1 2 NaN 3];
+            arrowArray = arrow.array(matlabArray);
+            testCase.verifyEqual(arrowArray.Valid, [true; true; false; true]);
+        end
+
+        function InferNullsTrue(testCase)
+        % Verify InferNulls is true by default.
+            matlabArray = [1 2 NaN 3];
+            arrowArray = arrow.array(matlabArray, InferNulls=true);
+            testCase.verifyEqual(arrowArray.Valid, [true; true; false; true]);
+        end
+
+        function InferNullsFalse(testCase)
+        % Verify Valid is the expected logical vector when
+        % InferNulls=false.
+            matlabArray = [1 2 NaN 3];
+            arrowArray = arrow.array(matlabArray, InferNulls=false);
+            testCase.verifyEqual(arrowArray.Valid, [true; true; true; true]);
+        end
+
+        function ValidNameValuePair(testCase)
+        % Verify Valid is the expected vector when the Valid
+        % name-value pair is supplied.
+            matlabArray = [1 NaN NaN 3];
+            arrowArray = arrow.array(matlabArray, Valid=[1 2]);
+            testCase.verifyEqual(arrowArray.Valid, [true; true; false; false]);
+        end
+    end
+end
\ No newline at end of file
diff --git a/matlab/test/arrow/array/tBooleanArray.m 
b/matlab/test/arrow/array/tBooleanArray.m
index e27ca11285..df7f052597 100644
--- a/matlab/test/arrow/array/tBooleanArray.m
+++ b/matlab/test/arrow/array/tBooleanArray.m
@@ -18,7 +18,7 @@ classdef tBooleanArray < matlab.unittest.TestCase
 
       properties
         ArrowArrayClassName(1, 1) string = "arrow.array.BooleanArray"
-        ArrowArrayConstructor = @arrow.array.BooleanArray
+        ArrowArrayConstructorFcn = @arrow.array.BooleanArray.fromMATLAB
         MatlabArrayFcn = @logical
         MatlabConversionFcn = @logical
         NullSubstitutionValue = false
@@ -36,34 +36,34 @@ classdef tBooleanArray < matlab.unittest.TestCase
 
     methods(Test)
         function BasicTest(tc)
-            A = tc.ArrowArrayConstructor(tc.MatlabArrayFcn([true false true]));
+            A = tc.ArrowArrayConstructorFcn(tc.MatlabArrayFcn([true false 
true]));
             className = string(class(A));
             tc.verifyEqual(className, tc.ArrowArrayClassName);
         end
 
         function ToMATLAB(tc)
             % Create array from a scalar
-            A1 = tc.ArrowArrayConstructor(tc.MatlabArrayFcn(true));
+            A1 = tc.ArrowArrayConstructorFcn(tc.MatlabArrayFcn(true));
             data = toMATLAB(A1);
             tc.verifyEqual(data, tc.MatlabArrayFcn(true));
 
             % Create array from a vector
-            A2 = tc.ArrowArrayConstructor(tc.MatlabArrayFcn([true false 
true]));
+            A2 = tc.ArrowArrayConstructorFcn(tc.MatlabArrayFcn([true false 
true]));
             data = toMATLAB(A2);
             tc.verifyEqual(data, tc.MatlabArrayFcn([true false true]'));
 
             % Create a BooleanArray from an empty 0x0 logical vector
-            A3 = tc.ArrowArrayConstructor(tc.MatlabArrayFcn(logical.empty(0, 
0)));
+            A3 = 
tc.ArrowArrayConstructorFcn(tc.MatlabArrayFcn(logical.empty(0, 0)));
             data = toMATLAB(A3);
             tc.verifyEqual(data, tc.MatlabArrayFcn(reshape([], 0, 1)));
 
             % Create a BooleanArray from an empty 0x1 logical vector
-            A4= tc.ArrowArrayConstructor(tc.MatlabArrayFcn(logical.empty(0, 
1)));
+            A4= tc.ArrowArrayConstructorFcn(tc.MatlabArrayFcn(logical.empty(0, 
1)));
             data = toMATLAB(A4);
             tc.verifyEqual(data, tc.MatlabArrayFcn(reshape([], 0, 1)));
 
             % Create a BooleanArray from an empty 1x0 logical vector
-            A5= tc.ArrowArrayConstructor(tc.MatlabArrayFcn(logical.empty(0, 
1)));
+            A5= tc.ArrowArrayConstructorFcn(tc.MatlabArrayFcn(logical.empty(0, 
1)));
             data = toMATLAB(A5);
             tc.verifyEqual(data, tc.MatlabArrayFcn(reshape([], 0, 1)));
         end
@@ -72,27 +72,27 @@ classdef tBooleanArray < matlab.unittest.TestCase
         % Tests the type-specific conversion method (i.e. logical)
 
             % Create array from a scalar
-            A1 = tc.ArrowArrayConstructor(tc.MatlabArrayFcn(true));
+            A1 = tc.ArrowArrayConstructorFcn(tc.MatlabArrayFcn(true));
             data = tc.MatlabConversionFcn(A1);
             tc.verifyEqual(data, tc.MatlabArrayFcn(true));
 
             % Create array from a vector
-            A2 = tc.ArrowArrayConstructor(tc.MatlabArrayFcn([true false 
true]));
+            A2 = tc.ArrowArrayConstructorFcn(tc.MatlabArrayFcn([true false 
true]));
             data = tc.MatlabConversionFcn(A2);
             tc.verifyEqual(data, tc.MatlabArrayFcn([true false true]'));
 
             % Create a BooleanArray from an empty 0x0 logical vector
-            A3 = tc.ArrowArrayConstructor(tc.MatlabArrayFcn(logical.empty(0, 
0)));
+            A3 = 
tc.ArrowArrayConstructorFcn(tc.MatlabArrayFcn(logical.empty(0, 0)));
             data = tc.MatlabConversionFcn(A3);
             tc.verifyEqual(data, tc.MatlabArrayFcn(reshape([], 0, 1)));
 
             % Create a BooleanArray from an empty 0x1 logical vector
-            A4= tc.ArrowArrayConstructor(tc.MatlabArrayFcn(logical.empty(0, 
1)));
+            A4= tc.ArrowArrayConstructorFcn(tc.MatlabArrayFcn(logical.empty(0, 
1)));
             data = tc.MatlabConversionFcn(A4);
             tc.verifyEqual(data, tc.MatlabArrayFcn(reshape([], 0, 1)));
 
             % Create a BooleanArray from an empty 1x0 logical vector
-            A5= tc.ArrowArrayConstructor(tc.MatlabArrayFcn(logical.empty(0, 
1)));
+            A5= tc.ArrowArrayConstructorFcn(tc.MatlabArrayFcn(logical.empty(0, 
1)));
             data = tc.MatlabConversionFcn(A5);
             tc.verifyEqual(data, tc.MatlabArrayFcn(reshape([], 0, 1)));
         end
@@ -101,7 +101,7 @@ classdef tBooleanArray < matlab.unittest.TestCase
             % Verify the expected elements are treated as null when Valid
             % is provided as a logical array
             data = tc.MatlabArrayFcn([true false true]');
-            arrowArray = tc.ArrowArrayConstructor(data, Valid=[false true 
true]);
+            arrowArray = tc.ArrowArrayConstructorFcn(data, Valid=[false true 
true]);
 
             expectedData = data;
             expectedData(1) = tc.NullSubstitutionValue;
@@ -114,7 +114,7 @@ classdef tBooleanArray < matlab.unittest.TestCase
             % Verify the expected elements are treated as null when Valid
             % is provided as a array of indices
             data = tc.MatlabArrayFcn([true false true]');
-            arrowArray = tc.ArrowArrayConstructor(data, Valid=[1, 2]);
+            arrowArray = tc.ArrowArrayConstructorFcn(data, Valid=[1, 2]);
 
             expectedData = data;
             expectedData(3) = tc.NullSubstitutionValue;
@@ -126,7 +126,7 @@ classdef tBooleanArray < matlab.unittest.TestCase
             % Make sure the optimization where the valid-bitmap is stored as
             % a nullptr works as expected.
             expectedData = data;
-            arrowArray = tc.ArrowArrayConstructor(data, Valid=[1, 2, 3]);
+            arrowArray = tc.ArrowArrayConstructorFcn(data, Valid=[1, 2, 3]);
             tc.verifyEqual(tc.MatlabConversionFcn(arrowArray), expectedData);
             tc.verifyEqual(toMATLAB(arrowArray), expectedData);
             tc.verifyEqual(arrowArray.Valid, [true; true; true]);
@@ -135,26 +135,27 @@ classdef tBooleanArray < matlab.unittest.TestCase
         function ErrorIfNonVector(tc)
             data = tc.MatlabArrayFcn([true false true false true false true 
false true]);
             data = reshape(data, 3, 1, 3);
-            fcn = @() tc.ArrowArrayConstructor(tc.MatlabArrayFcn(data));
-            tc.verifyError(fcn, "MATLAB:expectedVector");
+            fcn = @() tc.ArrowArrayConstructorFcn(tc.MatlabArrayFcn(data));
+            tc.verifyError(fcn, "arrow:array:InvalidShape");
         end
 
-        function ErrorIfEmptyArrayIsNotTwoDimensional(tc)
-            data = tc.MatlabArrayFcn(reshape(logical.empty(0, 0), [1 0 0]));
-            fcn = @() tc.ArrowArrayConstructor(data);
-            tc.verifyError(fcn, "MATLAB:expected2D");
+        function AllowNDimensionalEmptyArray(tc)
+            data = tc.MatlabArrayFcn(reshape([], [1 0 0]));
+            A = tc.ArrowArrayConstructorFcn(data);
+            tc.verifyEqual(A.Length, int64(0));
+            tc.verifyEqual(toMATLAB(A), tc.MatlabArrayFcn(reshape([], [0 1])));
         end
 
         function ErrorIfSparseArray(tc)
             data = tc.MatlabArrayFcn(sparse([true false true]));
-            fcn = @() tc.ArrowArrayConstructor(data);
-            tc.verifyError(fcn, "MATLAB:expectedNonsparse");
+            fcn = @() tc.ArrowArrayConstructorFcn(data);
+            tc.verifyError(fcn, "arrow:array:Sparse");
         end
 
         function TestArrowType(tc)
         % Verify the array has the expected arrow.type.Type object
             data = tc.MatlabArrayFcn([true false]);
-            arrowArray = tc.ArrowArrayConstructor(data);
+            arrowArray = tc.ArrowArrayConstructorFcn(data);
             tc.verifyEqual(arrowArray.Type.ID, tc.ArrowType.ID);
         end
     end
diff --git a/matlab/test/arrow/array/tFloat32Array.m 
b/matlab/test/arrow/array/tFloat32Array.m
index f007e2b422..2ec9b90b4d 100644
--- a/matlab/test/arrow/array/tFloat32Array.m
+++ b/matlab/test/arrow/array/tFloat32Array.m
@@ -18,7 +18,7 @@ classdef tFloat32Array < hNumericArray
 
     properties
         ArrowArrayClassName = "arrow.array.Float32Array"
-        ArrowArrayConstructor = @arrow.array.Float32Array
+        ArrowArrayConstructorFcn = @arrow.array.Float32Array.fromMATLAB
         MatlabConversionFcn = @single % single method on class
         MatlabArrayFcn = @single % single function
         MaxValue = realmax("single")
@@ -29,7 +29,7 @@ classdef tFloat32Array < hNumericArray
 
     methods(Test)
         function InfValues(testCase)
-            A1 = arrow.array.Float32Array(single([Inf -Inf]));
+            A1 = testCase.ArrowArrayConstructorFcn(single([Inf -Inf]));
             data = single(A1);
             testCase.verifyEqual(data, single([Inf -Inf]'));
         end
@@ -38,7 +38,7 @@ classdef tFloat32Array < hNumericArray
             % Create a MATLAB array with one null value (i.e. one NaN).
             % Verify NaN is considered a null value by default.
             matlabArray = single([1, NaN, 3]');
-            arrowArray = arrow.array.Float32Array(matlabArray);
+            arrowArray = testCase.ArrowArrayConstructorFcn(matlabArray);
             expectedValid = [true, false, true]';
             testCase.verifyEqual(arrowArray.Valid, expectedValid);
         end
@@ -47,13 +47,13 @@ classdef tFloat32Array < hNumericArray
             matlabArray = single([1, NaN, 3]);
 
             % Verify NaN is treated as a null value when InferNulls=true.
-            arrowArray1 = arrow.array.Float32Array(matlabArray, 
InferNulls=true);
+            arrowArray1 = testCase.ArrowArrayConstructorFcn(matlabArray, 
InferNulls=true);
             expectedValid1 = [true false true]';
             testCase.verifyEqual(arrowArray1.Valid, expectedValid1);
             testCase.verifyEqual(toMATLAB(arrowArray1), matlabArray');
 
             % Verify NaN is not treated as a null value when InferNulls=false.
-            arrowArray2 = arrow.array.Float32Array(matlabArray, 
InferNulls=false);
+            arrowArray2 = testCase.ArrowArrayConstructorFcn(matlabArray, 
InferNulls=false);
             expectedValid2 = [true true true]';
             testCase.verifyEqual(arrowArray2.Valid, expectedValid2);
             testCase.verifyEqual(toMATLAB(arrowArray2), matlabArray');
@@ -62,7 +62,7 @@ classdef tFloat32Array < hNumericArray
         function ValidNoNulls(testCase)
             % Create a MATLAB array with no null values (i.e. no NaNs).
             matlabArray = single([1, 2, 3]');
-            arrowArray = arrow.array.Float32Array(matlabArray);
+            arrowArray = testCase.ArrowArrayConstructorFcn(matlabArray);
             expectedValid = [true, true, true]';
             testCase.verifyEqual(arrowArray.Valid, expectedValid);
         end
@@ -70,7 +70,7 @@ classdef tFloat32Array < hNumericArray
         function ValidAllNulls(testCase)
             % Create a MATLAB array with all null values (i.e. all NaNs).
             matlabArray = single([NaN, NaN, NaN]');
-            arrowArray = arrow.array.Float32Array(matlabArray);
+            arrowArray = testCase.ArrowArrayConstructorFcn(matlabArray);
             expectedValid = [false, false, false]';
             testCase.verifyEqual(arrowArray.Valid, expectedValid);
         end
@@ -78,18 +78,18 @@ classdef tFloat32Array < hNumericArray
         function EmptyArrayValidBitmap(testCase)
             % Create an empty 0x0 MATLAB array.
             matlabArray = single.empty(0, 0);
-            arrowArray = arrow.array.Float32Array(matlabArray);
+            arrowArray = testCase.ArrowArrayConstructorFcn(matlabArray);
             expectedValid = logical.empty(0, 1);
             testCase.verifyEqual(arrowArray.Valid, expectedValid);
 
             % Create an empty 0x1 MATLAB array.
             matlabArray = single.empty(0, 1);
-            arrowArray = arrow.array.Float32Array(matlabArray);
+            arrowArray = testCase.ArrowArrayConstructorFcn(matlabArray);
             testCase.verifyEqual(arrowArray.Valid, expectedValid);
 
             % Create an empty 1x0 MATLAB array.
             matlabArray = single.empty(1, 0);
-            arrowArray = arrow.array.Float32Array(matlabArray);
+            arrowArray = testCase.ArrowArrayConstructorFcn(matlabArray);
             testCase.verifyEqual(arrowArray.Valid, expectedValid);
         end
 
@@ -97,7 +97,7 @@ classdef tFloat32Array < hNumericArray
             matlabArray = single([1 2 3]); 
 
             % Supply a logical vector for Valid
-            arrowArray = arrow.array.Float32Array(matlabArray, Valid=[false; 
true; true]);
+            arrowArray = testCase.ArrowArrayConstructorFcn(matlabArray, 
Valid=[false; true; true]);
             testCase.verifyEqual(arrowArray.Valid, [false; true; true]);
             testCase.verifyEqual(toMATLAB(arrowArray), single([NaN; 2; 3]));
         end
@@ -106,7 +106,7 @@ classdef tFloat32Array < hNumericArray
             matlabArray = single([1 2 3]); 
 
             % Supply a numeric vector for Valid 
-            arrowArray = arrow.array.Float32Array(matlabArray, Valid=[1 3]);
+            arrowArray = testCase.ArrowArrayConstructorFcn(matlabArray, 
Valid=[1 3]);
             testCase.verifyEqual(arrowArray.Valid, [true; false; true]);
             testCase.verifyEqual(toMATLAB(arrowArray), single([1; NaN; 3]));
         end
diff --git a/matlab/test/arrow/array/tFloat64Array.m 
b/matlab/test/arrow/array/tFloat64Array.m
index 9b30ec8f25..a39a3d1e62 100755
--- a/matlab/test/arrow/array/tFloat64Array.m
+++ b/matlab/test/arrow/array/tFloat64Array.m
@@ -18,7 +18,7 @@ classdef tFloat64Array < hNumericArray
 
     properties
         ArrowArrayClassName = "arrow.array.Float64Array"
-        ArrowArrayConstructor = @arrow.array.Float64Array
+        ArrowArrayConstructorFcn = @arrow.array.Float64Array.fromMATLAB
         MatlabConversionFcn = @double % double method on class
         MatlabArrayFcn = @double % double function
         MaxValue = realmax("double")
@@ -29,21 +29,21 @@ classdef tFloat64Array < hNumericArray
 
     methods(Test)
         function InfValues(testCase)
-            A1 = arrow.array.Float64Array([Inf -Inf]);
+            A1 = testCase.ArrowArrayConstructorFcn([Inf -Inf]);
             data = double(A1);
             testCase.verifyEqual(data, [Inf -Inf]');
         end
 
         function ErrorIfSparse(testCase)
-            fcn = @() arrow.array.Float64Array(sparse(ones([10 1])));
-            testCase.verifyError(fcn, "MATLAB:expectedNonsparse");
+            fcn = @() testCase.ArrowArrayConstructorFcn(sparse(ones([10 1])));
+            testCase.verifyError(fcn, "arrow:array:Sparse");
         end
 
         function ValidBasic(testCase)
             % Create a MATLAB array with one null value (i.e. one NaN).
             % Verify NaN is considered a null value by default.
             matlabArray = [1, NaN, 3]';
-            arrowArray = arrow.array.Float64Array(matlabArray);
+            arrowArray = testCase.ArrowArrayConstructorFcn(matlabArray);
             expectedValid = [true, false, true]';
             testCase.verifyEqual(arrowArray.Valid, expectedValid);
         end
@@ -52,13 +52,13 @@ classdef tFloat64Array < hNumericArray
             matlabArray = [1, NaN, 3];
 
             % Verify NaN is treated as a null value when InferNulls=true.
-            arrowArray1 = arrow.array.Float64Array(matlabArray, 
InferNulls=true);
+            arrowArray1 = testCase.ArrowArrayConstructorFcn(matlabArray, 
InferNulls=true);
             expectedValid1 = [true false true]';
             testCase.verifyEqual(arrowArray1.Valid, expectedValid1);
             testCase.verifyEqual(toMATLAB(arrowArray1), matlabArray');
 
             % Verify NaN is not treated as a null value when InferNulls=false.
-            arrowArray2 = arrow.array.Float64Array(matlabArray, 
InferNulls=false);
+            arrowArray2 = testCase.ArrowArrayConstructorFcn(matlabArray, 
InferNulls=false);
             expectedValid2 = [true true true]';
             testCase.verifyEqual(arrowArray2.Valid, expectedValid2);
             testCase.verifyEqual(toMATLAB(arrowArray2), matlabArray');
@@ -67,7 +67,7 @@ classdef tFloat64Array < hNumericArray
         function ValidNoNulls(testCase)
             % Create a MATLAB array with no null values (i.e. no NaNs).
             matlabArray = [1, 2, 3]';
-            arrowArray = arrow.array.Float64Array(matlabArray);
+            arrowArray = testCase.ArrowArrayConstructorFcn(matlabArray);
             expectedValid = [true, true, true]';
             testCase.verifyEqual(arrowArray.Valid, expectedValid);
         end
@@ -75,7 +75,7 @@ classdef tFloat64Array < hNumericArray
         function ValidAllNulls(testCase)
             % Create a MATLAB array with all null values (i.e. all NaNs).
             matlabArray = [NaN, NaN, NaN]';
-            arrowArray = arrow.array.Float64Array(matlabArray);
+            arrowArray = testCase.ArrowArrayConstructorFcn(matlabArray);
             expectedValid = [false, false, false]';
             testCase.verifyEqual(arrowArray.Valid, expectedValid);
         end
@@ -83,18 +83,18 @@ classdef tFloat64Array < hNumericArray
         function EmptyArrayValidBitmap(testCase)
             % Create an empty 0x0 MATLAB array.
             matlabArray = double.empty(0, 0);
-            arrowArray = arrow.array.Float64Array(matlabArray);
+            arrowArray = testCase.ArrowArrayConstructorFcn(matlabArray);
             expectedValid = logical.empty(0, 1);
             testCase.verifyEqual(arrowArray.Valid, expectedValid);
 
             % Create an empty 0x1 MATLAB array.
             matlabArray = double.empty(0, 1);
-            arrowArray = arrow.array.Float64Array(matlabArray);
+            arrowArray = testCase.ArrowArrayConstructorFcn(matlabArray);
             testCase.verifyEqual(arrowArray.Valid, expectedValid);
 
             % Create an empty 1x0 MATLAB array.
             matlabArray = double.empty(1, 0);
-            arrowArray = arrow.array.Float64Array(matlabArray);
+            arrowArray = testCase.ArrowArrayConstructorFcn(matlabArray);
             testCase.verifyEqual(arrowArray.Valid, expectedValid);
         end
 
@@ -102,7 +102,7 @@ classdef tFloat64Array < hNumericArray
             matlabArray = [1 2 3]; 
 
             % Supply a logical vector for Valid
-            arrowArray = arrow.array.Float64Array(matlabArray, Valid=[false; 
true; true]);
+            arrowArray = testCase.ArrowArrayConstructorFcn(matlabArray, 
Valid=[false; true; true]);
             testCase.verifyEqual(arrowArray.Valid, [false; true; true]);
             testCase.verifyEqual(toMATLAB(arrowArray), [NaN; 2; 3]);
         end
@@ -111,7 +111,7 @@ classdef tFloat64Array < hNumericArray
             matlabArray = [1 2 3]; 
 
             % Supply a numeric vector for Valid 
-            arrowArray = arrow.array.Float64Array(matlabArray, Valid=[1 3]);
+            arrowArray = testCase.ArrowArrayConstructorFcn(matlabArray, 
Valid=[1 3]);
             testCase.verifyEqual(arrowArray.Valid, [true; false; true]);
             testCase.verifyEqual(toMATLAB(arrowArray), [1; NaN; 3]);
         end
diff --git a/matlab/test/arrow/array/tInt16Array.m 
b/matlab/test/arrow/array/tInt16Array.m
index 9cb5fdc1d1..391c8ccb62 100644
--- a/matlab/test/arrow/array/tInt16Array.m
+++ b/matlab/test/arrow/array/tInt16Array.m
@@ -18,7 +18,7 @@ classdef tInt16Array < hNumericArray
     
     properties
         ArrowArrayClassName = "arrow.array.Int16Array"
-        ArrowArrayConstructor = @arrow.array.Int16Array
+        ArrowArrayConstructorFcn = @arrow.array.Int16Array.fromMATLAB
         MatlabConversionFcn = @int16 % int16 method on class
         MatlabArrayFcn = @int16 % int16 function
         MaxValue = intmax("int16")
diff --git a/matlab/test/arrow/array/tInt32Array.m 
b/matlab/test/arrow/array/tInt32Array.m
index b45705592d..accf707359 100644
--- a/matlab/test/arrow/array/tInt32Array.m
+++ b/matlab/test/arrow/array/tInt32Array.m
@@ -18,7 +18,7 @@ classdef tInt32Array < hNumericArray
 
     properties
         ArrowArrayClassName = "arrow.array.Int32Array"
-        ArrowArrayConstructor = @arrow.array.Int32Array
+        ArrowArrayConstructorFcn = @arrow.array.Int32Array.fromMATLAB
         MatlabConversionFcn = @int32 % int32 method on class
         MatlabArrayFcn = @int32 % int32 function
         MaxValue = intmax("int32")
diff --git a/matlab/test/arrow/array/tInt64Array.m 
b/matlab/test/arrow/array/tInt64Array.m
index 0b38f58547..909e9af866 100644
--- a/matlab/test/arrow/array/tInt64Array.m
+++ b/matlab/test/arrow/array/tInt64Array.m
@@ -18,7 +18,7 @@ classdef tInt64Array < hNumericArray
 
     properties
         ArrowArrayClassName = "arrow.array.Int64Array"
-        ArrowArrayConstructor = @arrow.array.Int64Array
+        ArrowArrayConstructorFcn = @arrow.array.Int64Array.fromMATLAB
         MatlabConversionFcn = @int64 % int64 method on class
         MatlabArrayFcn = @int64 % int64 function
         MaxValue = intmax("int64")
diff --git a/matlab/test/arrow/array/tInt8Array.m 
b/matlab/test/arrow/array/tInt8Array.m
index 8ce8e4e9b2..2817b7b61f 100644
--- a/matlab/test/arrow/array/tInt8Array.m
+++ b/matlab/test/arrow/array/tInt8Array.m
@@ -18,7 +18,7 @@ classdef tInt8Array < hNumericArray
     
     properties
         ArrowArrayClassName = "arrow.array.Int8Array"
-        ArrowArrayConstructor = @arrow.array.Int8Array
+        ArrowArrayConstructorFcn = @arrow.array.Int8Array.fromMATLAB
         MatlabConversionFcn = @int8 % int8 method on class
         MatlabArrayFcn = @int8 % int8 function
         MaxValue = intmax("int8")
diff --git a/matlab/test/arrow/array/tStringArray.m 
b/matlab/test/arrow/array/tStringArray.m
index dbb2adca0c..85628ce421 100644
--- a/matlab/test/arrow/array/tStringArray.m
+++ b/matlab/test/arrow/array/tStringArray.m
@@ -18,7 +18,7 @@ classdef tStringArray < matlab.unittest.TestCase
 
       properties
         ArrowArrayClassName(1, 1) string = "arrow.array.StringArray"
-        ArrowArrayConstructor = @arrow.array.StringArray
+        ArrowArrayConstructorFcn = @arrow.array.StringArray.fromMATLAB
         MatlabArrayFcn = @string
         MatlabConversionFcn = @string
         NullSubstitutionValue = string(missing)
@@ -36,34 +36,34 @@ classdef tStringArray < matlab.unittest.TestCase
 
     methods(Test)
         function BasicTest(tc)
-            A = tc.ArrowArrayConstructor(tc.MatlabArrayFcn(["A", "B", "C"]));
+            A = tc.ArrowArrayConstructorFcn(tc.MatlabArrayFcn(["A", "B", 
"C"]));
             className = string(class(A));
             tc.verifyEqual(className, tc.ArrowArrayClassName);
         end
 
         function ToMATLAB(tc)
             % Create array from a scalar
-            A1 = tc.ArrowArrayConstructor(tc.MatlabArrayFcn("A"));
+            A1 = tc.ArrowArrayConstructorFcn(tc.MatlabArrayFcn("A"));
             data = toMATLAB(A1);
             tc.verifyEqual(data, tc.MatlabArrayFcn("A"));
 
             % Create array from a vector
-            A2 = tc.ArrowArrayConstructor(tc.MatlabArrayFcn(["A", "B", "C"]));
+            A2 = tc.ArrowArrayConstructorFcn(tc.MatlabArrayFcn(["A", "B", 
"C"]));
             data = toMATLAB(A2);
             tc.verifyEqual(data, tc.MatlabArrayFcn(["A", "B", "C"]'));
 
             % Create a StringArray from an empty 0x0 string vector
-            A3 = tc.ArrowArrayConstructor(tc.MatlabArrayFcn(string.empty(0, 
0)));
+            A3 = tc.ArrowArrayConstructorFcn(tc.MatlabArrayFcn(string.empty(0, 
0)));
             data = toMATLAB(A3);
             tc.verifyEqual(data, tc.MatlabArrayFcn(reshape([], 0, 1)));
 
             % Create a StringArray from an empty 0x1 string vector
-            A4= tc.ArrowArrayConstructor(tc.MatlabArrayFcn(string.empty(0, 
1)));
+            A4= tc.ArrowArrayConstructorFcn(tc.MatlabArrayFcn(string.empty(0, 
1)));
             data = toMATLAB(A4);
             tc.verifyEqual(data, tc.MatlabArrayFcn(reshape([], 0, 1)));
 
             % Create a StringArray from an empty 1x0 string vector
-            A5= tc.ArrowArrayConstructor(tc.MatlabArrayFcn(string.empty(0, 
1)));
+            A5= tc.ArrowArrayConstructorFcn(tc.MatlabArrayFcn(string.empty(0, 
1)));
             data = toMATLAB(A5);
             tc.verifyEqual(data, tc.MatlabArrayFcn(reshape([], 0, 1)));
         end
@@ -72,27 +72,27 @@ classdef tStringArray < matlab.unittest.TestCase
             % Tests the type-specific conversion method (i.e. string)
 
             % Create array from a scalar
-            A1 = tc.ArrowArrayConstructor(tc.MatlabArrayFcn("A"));
+            A1 = tc.ArrowArrayConstructorFcn(tc.MatlabArrayFcn("A"));
             data = tc.MatlabConversionFcn(A1);
             tc.verifyEqual(data, tc.MatlabArrayFcn("A"));
 
             % Create array from a vector
-            A2 = tc.ArrowArrayConstructor(tc.MatlabArrayFcn(["A", "B", "C"]));
+            A2 = tc.ArrowArrayConstructorFcn(tc.MatlabArrayFcn(["A", "B", 
"C"]));
             data = tc.MatlabConversionFcn(A2);
             tc.verifyEqual(data, tc.MatlabArrayFcn(["A", "B", "C"]'));
 
             % Create a StringArray from an empty 0x0 string vector
-            A3 = tc.ArrowArrayConstructor(tc.MatlabArrayFcn(string.empty(0, 
0)));
+            A3 = tc.ArrowArrayConstructorFcn(tc.MatlabArrayFcn(string.empty(0, 
0)));
             data = tc.MatlabConversionFcn(A3);
             tc.verifyEqual(data, tc.MatlabArrayFcn(reshape([], 0, 1)));
 
             % Create a StringArray from an empty 0x1 string vector
-            A4= tc.ArrowArrayConstructor(tc.MatlabArrayFcn(string.empty(0, 
1)));
+            A4= tc.ArrowArrayConstructorFcn(tc.MatlabArrayFcn(string.empty(0, 
1)));
             data = tc.MatlabConversionFcn(A4);
             tc.verifyEqual(data, tc.MatlabArrayFcn(reshape([], 0, 1)));
 
             % Create a StringArray from an empty 1x0 string vector
-            A5= tc.ArrowArrayConstructor(tc.MatlabArrayFcn(string.empty(0, 
1)));
+            A5= tc.ArrowArrayConstructorFcn(tc.MatlabArrayFcn(string.empty(0, 
1)));
             data = tc.MatlabConversionFcn(A5);
             tc.verifyEqual(data, tc.MatlabArrayFcn(reshape([], 0, 1)));
         end
@@ -101,7 +101,7 @@ classdef tStringArray < matlab.unittest.TestCase
             % Verify the expected elements are treated as null when Valid
             % is provided as a logical array
             data = tc.MatlabArrayFcn(["A", "B", "C"]');
-            arrowArray = tc.ArrowArrayConstructor(data, Valid=[false true 
true]);
+            arrowArray = tc.ArrowArrayConstructorFcn(data, Valid=[false true 
true]);
 
             expectedData = data;
             expectedData(1) = tc.NullSubstitutionValue;
@@ -114,7 +114,7 @@ classdef tStringArray < matlab.unittest.TestCase
             % Verify the expected elements are treated as null when Valid
             % is provided as a array of indices
             data = tc.MatlabArrayFcn(["A", "B", "C"]');
-            arrowArray = tc.ArrowArrayConstructor(data, Valid=[1, 2]);
+            arrowArray = tc.ArrowArrayConstructorFcn(data, Valid=[1, 2]);
 
             expectedData = data;
             expectedData(3) = tc.NullSubstitutionValue;
@@ -126,7 +126,7 @@ classdef tStringArray < matlab.unittest.TestCase
             % Make sure the optimization where the valid-bitmap is stored as
             % a nullptr works as expected.
             expectedData = data;
-            arrowArray = tc.ArrowArrayConstructor(data, Valid=[1, 2, 3]);
+            arrowArray = tc.ArrowArrayConstructorFcn(data, Valid=[1, 2, 3]);
             tc.verifyEqual(tc.MatlabConversionFcn(arrowArray), expectedData);
             tc.verifyEqual(toMATLAB(arrowArray), expectedData);
             tc.verifyEqual(arrowArray.Valid, [true; true; true]);
@@ -135,20 +135,21 @@ classdef tStringArray < matlab.unittest.TestCase
         function ErrorIfNonVector(tc)
             data = tc.MatlabArrayFcn(["A", "B", "A", "B", "A", "B", "A", "B", 
"A"]);
             data = reshape(data, 3, 1, 3);
-            fcn = @() tc.ArrowArrayConstructor(tc.MatlabArrayFcn(data));
-            tc.verifyError(fcn, "MATLAB:expectedVector");
+            fcn = @() tc.ArrowArrayConstructorFcn(tc.MatlabArrayFcn(data));
+            tc.verifyError(fcn, "arrow:array:InvalidShape");
         end
 
-        function ErrorIfEmptyArrayIsNotTwoDimensional(tc)
+        function AllowNDimensionalEmptyArray(tc)
             data = tc.MatlabArrayFcn(reshape(string.empty(0, 0), [1 0 0]));
-            fcn = @() tc.ArrowArrayConstructor(data);
-            tc.verifyError(fcn, "MATLAB:expected2D");
+            arrowArray = tc.ArrowArrayConstructorFcn(data);
+            tc.verifyEqual(arrowArray.Length, int64(0));
+            tc.verifyEqual(toMATLAB(arrowArray), string.empty(0, 1));
         end
 
         function TestArrowType(tc)
             % Verify the array has the expected arrow.type.Type object
             data = tc.MatlabArrayFcn(["A", "B"]);
-            arrowArray = tc.ArrowArrayConstructor(data);
+            arrowArray = tc.ArrowArrayConstructorFcn(data);
             tc.verifyEqual(arrowArray.Type.ID, tc.ArrowType.ID);
         end
 
@@ -160,7 +161,7 @@ classdef tStringArray < matlab.unittest.TestCase
             mango = "🥭";
             
             matlabArray = tc.MatlabArrayFcn([smiley; tree; mango]);
-            arrowArray = tc.ArrowArrayConstructor(matlabArray);
+            arrowArray = tc.ArrowArrayConstructorFcn(matlabArray);
             matlabArrayConverted = toMATLAB(arrowArray);
             tc.verifyEqual(matlabArrayConverted, matlabArray);
         end
@@ -169,7 +170,7 @@ classdef tStringArray < matlab.unittest.TestCase
             % Verify that string(missing) values get mapped to the empty
             % string value when InferNulls=false.
             matlabArray = tc.MatlabArrayFcn(["A"; string(missing); 
string(missing)]);
-            arrowArray = tc.ArrowArrayConstructor(matlabArray, 
InferNulls=false);
+            arrowArray = tc.ArrowArrayConstructorFcn(matlabArray, 
InferNulls=false);
             matlabArrayConverted = toMATLAB(arrowArray);
             tc.verifyEqual(matlabArrayConverted, ["A"; ""; ""]);
         end
@@ -180,25 +181,25 @@ classdef tStringArray < matlab.unittest.TestCase
 
             % Row vector
             matlabArray = {'A', 'B', 'C'};
-            arrowArray = tc.ArrowArrayConstructor(matlabArray);
+            arrowArray = tc.ArrowArrayConstructorFcn(matlabArray);
             matlabArrayConverted = toMATLAB(arrowArray);
             tc.verifyEqual(matlabArrayConverted, string(matlabArray'));
 
             % Column vector
             matlabArray = {'A'; 'B'; 'C'};
-            arrowArray = tc.ArrowArrayConstructor(matlabArray);
+            arrowArray = tc.ArrowArrayConstructorFcn(matlabArray);
             matlabArrayConverted = toMATLAB(arrowArray);
             tc.verifyEqual(matlabArrayConverted, string(matlabArray));
 
             % One element cellstr
             matlabArray = {''};
-            arrowArray = tc.ArrowArrayConstructor(matlabArray);
+            arrowArray = tc.ArrowArrayConstructorFcn(matlabArray);
             matlabArrayConverted = toMATLAB(arrowArray);
             tc.verifyEqual(matlabArrayConverted, string(matlabArray));
 
             % Empty cell
             matlabArray = {};
-            arrowArray = tc.ArrowArrayConstructor(matlabArray);
+            arrowArray = tc.ArrowArrayConstructorFcn(matlabArray);
             matlabArrayConverted = toMATLAB(arrowArray);
             tc.verifyEqual(matlabArrayConverted, string.empty(0, 1));
         end
@@ -209,23 +210,23 @@ classdef tStringArray < matlab.unittest.TestCase
 
             % Row vector
             matlabArray = 'abc';
-            tc.verifyError(@() tc.ArrowArrayConstructor(matlabArray), 
"MATLAB:invalidType");
+            tc.verifyError(@() tc.ArrowArrayConstructorFcn(matlabArray), 
"arrow:array:InvalidType");
 
             % Column vector
             matlabArray = ['a';'b';'c'];
-            tc.verifyError(@() tc.ArrowArrayConstructor(matlabArray), 
"MATLAB:invalidType");
+            tc.verifyError(@() tc.ArrowArrayConstructorFcn(matlabArray), 
"arrow:array:InvalidType");
 
             % Empty char (0x0)
             matlabArray = '';
-            tc.verifyError(@() tc.ArrowArrayConstructor(matlabArray), 
"MATLAB:invalidType");
+            tc.verifyError(@() tc.ArrowArrayConstructorFcn(matlabArray), 
"arrow:array:InvalidType");
 
             % Empty char (0x1)
             matlabArray = char.empty(0, 1);
-            tc.verifyError(@() tc.ArrowArrayConstructor(matlabArray), 
"MATLAB:invalidType");
+            tc.verifyError(@() tc.ArrowArrayConstructorFcn(matlabArray), 
"arrow:array:InvalidType");
 
             % Empty char (1x0)
             matlabArray = char.empty(1, 0);
-            tc.verifyError(@() tc.ArrowArrayConstructor(matlabArray), 
"MATLAB:invalidType");
+            tc.verifyError(@() tc.ArrowArrayConstructorFcn(matlabArray), 
"arrow:array:InvalidType");
         end
     end
 end
diff --git a/matlab/test/arrow/array/tTimestampArray.m 
b/matlab/test/arrow/array/tTimestampArray.m
index b0a902f319..5b7182c386 100644
--- a/matlab/test/arrow/array/tTimestampArray.m
+++ b/matlab/test/arrow/array/tTimestampArray.m
@@ -16,6 +16,10 @@
 classdef tTimestampArray < matlab.unittest.TestCase
 % Tests for arrow.array.TimestampArray
 
+    properties
+        ArrowArrayConstructorFcn = @arrow.array.TimestampArray.fromMATLAB
+    end
+
     properties(TestParameter)
         TimeZone = {"" "America/New_York"}
         TimeUnit = {arrow.type.TimeUnit.Second arrow.type.TimeUnit.Millisecond
@@ -25,26 +29,25 @@ classdef tTimestampArray < matlab.unittest.TestCase
     methods(Test)
         function Basic(tc, TimeZone)
             dates = datetime(2023, 6, 22, TimeZone=TimeZone) + days(0:4);
-            arrowArray = arrow.array.TimestampArray(dates);
+            arrowArray = tc.ArrowArrayConstructorFcn(dates);
             className = string(class(arrowArray));
             tc.verifyEqual(className, "arrow.array.TimestampArray");
         end
 
         function TestLength(testCase, TimeZone)
         % Verify the Length property.
-            import arrow.array.TimestampArray
 
             dates = datetime.empty(0, 1);
             dates.TimeZone = TimeZone;
-            arrowArray = TimestampArray(dates);
+            arrowArray = testCase.ArrowArrayConstructorFcn(dates);
             testCase.verifyEqual(arrowArray.Length, int64(0));
 
             dates = datetime(2023, 6, 22, TimeZone=TimeZone);
-            arrowArray = TimestampArray(dates);
+            arrowArray = testCase.ArrowArrayConstructorFcn(dates);
             testCase.verifyEqual(arrowArray.Length, int64(1));
 
             dates = datetime(2023, 6, 22, TimeZone=TimeZone) + days(0:4);
-            arrowArray = TimestampArray(dates);
+            arrowArray = testCase.ArrowArrayConstructorFcn(dates);
             testCase.verifyEqual(arrowArray.Length, int64(5));
         end
 
@@ -54,76 +57,72 @@ classdef tTimestampArray < matlab.unittest.TestCase
             import arrow.array.TimestampArray
 
             dates = datetime(2023, 6, 22, TimeZone=TimeZone) + days(0:4);
-            arrowArray = TimestampArray(dates);
+            arrowArray = testCase.ArrowArrayConstructorFcn(dates);
             testCase.verifyTimestampType(arrowArray.Type, 
arrow.type.TimeUnit.Microsecond, TimeZone);
         end
 
         function TestSupplyTimeUnit(testCase, TimeZone)
         % Supply the TimeUnit name-value pair at construction.
-            import arrow.array.TimestampArray
 
             dates = datetime(2023, 6, 22, TimeZone=TimeZone) + days(0:4);
 
-            arrowArray = TimestampArray(dates, TimeUnit="Second");
+            arrowArray = testCase.ArrowArrayConstructorFcn(dates, 
TimeUnit="Second");
             testCase.verifyTimestampType(arrowArray.Type, 
arrow.type.TimeUnit.Second, TimeZone);
 
-            arrowArray = TimestampArray(dates, TimeUnit="Millisecond");
+            arrowArray = testCase.ArrowArrayConstructorFcn(dates, 
TimeUnit="Millisecond");
             testCase.verifyTimestampType(arrowArray.Type, 
arrow.type.TimeUnit.Millisecond, TimeZone);
 
-            arrowArray = TimestampArray(dates, TimeUnit="Microsecond");
+            arrowArray = testCase.ArrowArrayConstructorFcn(dates, 
TimeUnit="Microsecond");
             testCase.verifyTimestampType(arrowArray.Type, 
arrow.type.TimeUnit.Microsecond, TimeZone);
 
-            arrowArray = TimestampArray(dates, TimeUnit="Nanosecond");
+            arrowArray = testCase.ArrowArrayConstructorFcn(dates, 
TimeUnit="Nanosecond");
             testCase.verifyTimestampType(arrowArray.Type, 
arrow.type.TimeUnit.Nanosecond, TimeZone);
         end
 
         function TestToMATLAB(testCase, TimeUnit, TimeZone)
         % Verify toMATLAB() round-trips the original datetime array.
-            import arrow.array.TimestampArray
 
             dates = datetime(2023, 6, 22, TimeZone=TimeZone) + days(0:4);
 
-            arrowArray = arrow.array.TimestampArray(dates, TimeUnit=TimeUnit);
+            arrowArray = testCase.ArrowArrayConstructorFcn(dates, 
TimeUnit=TimeUnit);
             values = toMATLAB(arrowArray);
             testCase.verifyEqual(values, dates');
         end
 
         function TestDatetime(testCase, TimeUnit, TimeZone)
         % Verify datetime() round-trips the original datetime array.
-            import arrow.array.TimestampArray
 
             dates = datetime(2023, 6, 22, TimeZone=TimeZone) + days(0:4);
-            arrowArray = arrow.array.TimestampArray(dates, TimeUnit=TimeUnit);
+            arrowArray = testCase.ArrowArrayConstructorFcn(dates, 
TimeUnit=TimeUnit);
             values = datetime(arrowArray);
             testCase.verifyEqual(values, dates');
         end
 
         function TestValid(testCase, TimeZone)
         % Verify the Valid property returns the expected logical vector.
-            import arrow.array.TimestampArray
+
             dates = datetime(2023, 6, 22, TimeZone=TimeZone) + days(0:4);
             dates([2 4]) = NaT;
-            arrowArray = arrow.array.TimestampArray(dates);
+            arrowArray = testCase.ArrowArrayConstructorFcn(dates);
             testCase.verifyEqual(arrowArray.Valid, [true; false; true; false; 
true]);
             testCase.verifyEqual(toMATLAB(arrowArray), dates');
             testCase.verifyEqual(datetime(arrowArray), dates');
         end
 
         function TestInferNulls(testCase, TimeUnit, TimeZone)
-            import arrow.array.TimestampArray
 
             dates = datetime(2023, 6, 22, TimeZone=TimeZone) + days(0:4);
             dates([2 4]) = NaT;
 
             % Verify NaT is treated as a null value if InferNulls=true.
             expectedDates = dates';
-            arrowArray = arrow.array.TimestampArray(dates, TimeUnit=TimeUnit, 
InferNulls=true);
+            arrowArray = testCase.ArrowArrayConstructorFcn(dates, 
TimeUnit=TimeUnit, InferNulls=true);
             testCase.verifyEqual(arrowArray.Valid, [true; false; true; false; 
true]);
             testCase.verifyEqual(toMATLAB(arrowArray), expectedDates);
 
             % Verify NaT is not treated as a null value if InferNulls=false.
             % The NaT values are mapped to int64(0).
-            arrowArray = arrow.array.TimestampArray(dates, TimeUnit=TimeUnit, 
InferNulls=false);
+            arrowArray = testCase.ArrowArrayConstructorFcn(dates, 
TimeUnit=TimeUnit, InferNulls=false);
             testCase.verifyEqual(arrowArray.Valid, [true; true; true; true; 
true]);
             
             % If the TimestampArray is zoned, int64(0) may not correspond
@@ -134,13 +133,12 @@ classdef tTimestampArray < matlab.unittest.TestCase
         end
 
         function TestValidNVPair(testCase, TimeUnit, TimeZone)
-            import arrow.array.TimestampArray
 
             dates = datetime(2023, 6, 22, TimeZone=TimeZone) + days(0:4);
             dates([2 4]) = NaT;
             
             % Supply the Valid name-value pair as vector of indices.
-            arrowArray = arrow.array.TimestampArray(dates, TimeUnit=TimeUnit, 
Valid=[1 2 5]);
+            arrowArray = testCase.ArrowArrayConstructorFcn(dates, 
TimeUnit=TimeUnit, Valid=[1 2 5]);
             testCase.verifyEqual(arrowArray.Valid, [true; true; false; false; 
true]);
             expectedDates = dates';
             expectedDates(2) = getFillValue(TimeZone);
@@ -148,33 +146,41 @@ classdef tTimestampArray < matlab.unittest.TestCase
             testCase.verifyEqual(toMATLAB(arrowArray), expectedDates);
 
             % Supply the Valid name-value pair as a logical scalar.
-            arrowArray = arrow.array.TimestampArray(dates, TimeUnit=TimeUnit, 
Valid=false);
+            arrowArray = testCase.ArrowArrayConstructorFcn(dates, 
TimeUnit=TimeUnit, Valid=false);
             testCase.verifyEqual(arrowArray.Valid, [false; false; false; 
false; false]);
             expectedDates(:) = NaT;
             testCase.verifyEqual(toMATLAB(arrowArray), expectedDates);
         end
 
         function ErrorIfNonVector(testCase)
-            import arrow.array.TimestampArray
 
             dates = datetime(2023, 6, 2) + days(0:11);
             dates = reshape(dates, 2, 6);
-            fcn = @() TimestampArray(dates);
-            testCase.verifyError(fcn, "MATLAB:expectedVector");
+            fcn = @() testCase.ArrowArrayConstructorFcn(dates);
+            testCase.verifyError(fcn, "arrow:array:InvalidShape");
 
             dates = reshape(dates, 3, 2, 2);
-            fcn = @() TimestampArray(dates);
-            testCase.verifyError(fcn, "MATLAB:expectedVector");
+            fcn = @() testCase.ArrowArrayConstructorFcn(dates);
+            testCase.verifyError(fcn, "arrow:array:InvalidShape");
         end
 
         function EmptyDatetimeVector(testCase)
             import arrow.array.TimestampArray
 
             dates = datetime.empty(0, 0);
-            arrowArray = TimestampArray(dates);
+            arrowArray = testCase.ArrowArrayConstructorFcn(dates);
+            testCase.verifyEqual(arrowArray.Length, int64(0));
+            testCase.verifyEqual(arrowArray.Valid, logical.empty(0, 1));
+            testCase.verifyEqual(toMATLAB(arrowArray), datetime.empty(0, 1));
+
+            % test with NDimensional empty array
+            dates = datetime.empty(0, 1, 0);
+            arrowArray = testCase.ArrowArrayConstructorFcn(dates);
             testCase.verifyEqual(arrowArray.Length, int64(0));
             testCase.verifyEqual(arrowArray.Valid, logical.empty(0, 1));
             testCase.verifyEqual(toMATLAB(arrowArray), datetime.empty(0, 1));
+
+
         end
     end
 
diff --git a/matlab/test/arrow/array/tUInt16Array.m 
b/matlab/test/arrow/array/tUInt16Array.m
index 705d6eabc0..c3445b7c7c 100644
--- a/matlab/test/arrow/array/tUInt16Array.m
+++ b/matlab/test/arrow/array/tUInt16Array.m
@@ -18,7 +18,7 @@ classdef tUInt16Array < hNumericArray
     
     properties
         ArrowArrayClassName = "arrow.array.UInt16Array"
-        ArrowArrayConstructor = @arrow.array.UInt16Array
+        ArrowArrayConstructorFcn = @arrow.array.UInt16Array.fromMATLAB
         MatlabConversionFcn = @uint16 % uint16 method on class
         MatlabArrayFcn = @uint16 % uint16 function
         MaxValue = intmax("uint16")
diff --git a/matlab/test/arrow/array/tUInt32Array.m 
b/matlab/test/arrow/array/tUInt32Array.m
index 267a687738..e6372b8db7 100644
--- a/matlab/test/arrow/array/tUInt32Array.m
+++ b/matlab/test/arrow/array/tUInt32Array.m
@@ -18,7 +18,7 @@ classdef tUInt32Array < hNumericArray
 
     properties
         ArrowArrayClassName = "arrow.array.UInt32Array"
-        ArrowArrayConstructor = @arrow.array.UInt32Array
+        ArrowArrayConstructorFcn = @arrow.array.UInt32Array.fromMATLAB
         MatlabConversionFcn = @uint32 % uint32 method on class
         MatlabArrayFcn = @uint32 % uint32 function
         MaxValue = intmax("uint32")
diff --git a/matlab/test/arrow/array/tUInt64Array.m 
b/matlab/test/arrow/array/tUInt64Array.m
index b1a23a004d..16c3cc81cd 100644
--- a/matlab/test/arrow/array/tUInt64Array.m
+++ b/matlab/test/arrow/array/tUInt64Array.m
@@ -18,7 +18,7 @@ classdef tUInt64Array < hNumericArray
 
     properties
         ArrowArrayClassName = "arrow.array.UInt64Array"
-        ArrowArrayConstructor = @arrow.array.UInt64Array
+        ArrowArrayConstructorFcn = @arrow.array.UInt64Array.fromMATLAB
         MatlabConversionFcn = @uint64 % uint64 method on class
         MatlabArrayFcn = @uint64 % uint64 function
         MaxValue = intmax("uint64")
diff --git a/matlab/test/arrow/array/tUInt8Array.m 
b/matlab/test/arrow/array/tUInt8Array.m
index 3db79f8c0b..a27e3442ed 100644
--- a/matlab/test/arrow/array/tUInt8Array.m
+++ b/matlab/test/arrow/array/tUInt8Array.m
@@ -18,7 +18,7 @@ classdef tUInt8Array < hNumericArray
 
     properties
         ArrowArrayClassName = "arrow.array.UInt8Array"
-        ArrowArrayConstructor = @arrow.array.UInt8Array
+        ArrowArrayConstructorFcn = @arrow.array.UInt8Array.fromMATLAB
         MatlabConversionFcn = @uint8 % uint8 method on class
         MatlabArrayFcn = @uint8 % uint8 function
         MaxValue = intmax("uint8")
diff --git a/matlab/test/arrow/internal/validate/tNonsparse.m 
b/matlab/test/arrow/internal/validate/tNonsparse.m
new file mode 100644
index 0000000000..e2eb363fca
--- /dev/null
+++ b/matlab/test/arrow/internal/validate/tNonsparse.m
@@ -0,0 +1,44 @@
+%TNONSPARSE Unit tests for arrow.internal.validate.nonsparse.
+
+% Licensed to the Apache Software Foundation (ASF) under one or more
+% contributor license agreements.  See the NOTICE file distributed with
+% this work for additional information regarding copyright ownership.
+% The ASF licenses this file to you under the Apache License, Version
+% 2.0 (the "License"); you may not use this file except in compliance
+% with the License.  You may obtain a copy of the License at
+%
+%   http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS,
+% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+% implied.  See the License for the specific language governing
+% permissions and limitations under the License.
+classdef tNonsparse < matlab.unittest.TestCase
+    
+    methods(Test)
+        % Test methods
+        function ErrorIfSparseDouble(testCase)
+            fcn = @() arrow.internal.validate.nonsparse(sparse(ones([10 1])));
+            errid = "arrow:array:Sparse";
+            testCase.verifyError(fcn, errid);
+        end
+
+        function ErrorIfSparseLogical(testCase)
+            fcn = @() arrow.internal.validate.nonsparse(sparse(true([10 1])));
+            errid = "arrow:array:Sparse";
+            testCase.verifyError(fcn, errid);
+        end
+
+        function NoErrorIfNonSparseDouble(testCase)
+            fcn = @() arrow.internal.validate.nonsparse(ones([10 1]));
+            testCase.verifyWarningFree(fcn); 
+        end
+
+        function NoErrorIfNonSparseLogical(testCase)
+            fcn = @() arrow.internal.validate.nonsparse(true([10 1]));
+            testCase.verifyWarningFree(fcn); 
+        end
+    end
+    
+end
\ No newline at end of file
diff --git a/matlab/test/arrow/internal/validate/tNumeric.m 
b/matlab/test/arrow/internal/validate/tNumeric.m
new file mode 100644
index 0000000000..91c94233de
--- /dev/null
+++ b/matlab/test/arrow/internal/validate/tNumeric.m
@@ -0,0 +1,56 @@
+%TNUMERIC Unit tests for arrow.internal.validate.numeric.
+
+% Licensed to the Apache Software Foundation (ASF) under one or more
+% contributor license agreements.  See the NOTICE file distributed with
+% this work for additional information regarding copyright ownership.
+% The ASF licenses this file to you under the Apache License, Version
+% 2.0 (the "License"); you may not use this file except in compliance
+% with the License.  You may obtain a copy of the License at
+%
+%   http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS,
+% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+% implied.  See the License for the specific language governing
+% permissions and limitations under the License.
+
+classdef tNumeric < matlab.unittest.TestCase
+    
+    methods(Test)
+        
+        function ErrorIfWrongType(testCase)
+            data = [1 2 2 4];
+            fcn = @() arrow.internal.validate.numeric(data, "single");
+            errid = "arrow:array:InvalidType";            
+            testCase.verifyError(fcn, errid);
+        end
+
+        function ErrorIfNonVector(testCase)
+            data = [1 2; 2 4];
+            fcn = @() arrow.internal.validate.numeric(data, "double");
+            errid = "arrow:array:InvalidShape";            
+            testCase.verifyError(fcn, errid);
+        end
+
+        function ErrorIfNonsparse(testCase)
+            data = sparse([1 1 2 2]);
+            fcn = @() arrow.internal.validate.numeric(data, "double");
+            errid = "arrow:array:Sparse";            
+            testCase.verifyError(fcn, errid);
+        end
+
+        function ErrorIfComplex(testCase)
+            data = [10 + 3i 11 + 4i];
+            fcn = @() arrow.internal.validate.numeric(data, "double");
+            errid = "arrow:array:ComplexNumeric";            
+            testCase.verifyError(fcn, errid);
+        end
+
+        function NoErrorIfRealNonsparseNumericVector(testCase)
+            data = [10 11 12 13];
+            fcn = @() arrow.internal.validate.numeric(data, "double");
+            testCase.verifyWarningFree(fcn);
+        end
+    end
+end
\ No newline at end of file
diff --git a/matlab/test/arrow/args/tParseValidElements.m 
b/matlab/test/arrow/internal/validate/tParseValidElements.m
similarity index 99%
rename from matlab/test/arrow/args/tParseValidElements.m
rename to matlab/test/arrow/internal/validate/tParseValidElements.m
index 9d7586db95..9751327adc 100644
--- a/matlab/test/arrow/args/tParseValidElements.m
+++ b/matlab/test/arrow/internal/validate/tParseValidElements.m
@@ -186,5 +186,5 @@ function validElements = parseValidElements(data, opts)
         opts.InferNulls = true;
         opts.Valid
     end
-    validElements = arrow.args.parseValidElements(data, opts);
+    validElements = arrow.internal.validate.parseValidElements(data, opts);
 end
\ No newline at end of file
diff --git a/matlab/test/arrow/internal/validate/tRealNumeric.m 
b/matlab/test/arrow/internal/validate/tRealNumeric.m
new file mode 100644
index 0000000000..9b45a6e0b5
--- /dev/null
+++ b/matlab/test/arrow/internal/validate/tRealNumeric.m
@@ -0,0 +1,43 @@
+%TREALNUMERIC Unit tests for arrow.internal.validate.realnumeric.
+
+% Licensed to the Apache Software Foundation (ASF) under one or more
+% contributor license agreements.  See the NOTICE file distributed with
+% this work for additional information regarding copyright ownership.
+% The ASF licenses this file to you under the Apache License, Version
+% 2.0 (the "License"); you may not use this file except in compliance
+% with the License.  You may obtain a copy of the License at
+%
+%   http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS,
+% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+% implied.  See the License for the specific language governing
+% permissions and limitations under the License.
+
+classdef tRealNumeric < matlab.unittest.TestCase
+
+    properties(TestParameter)
+        NumericType = struct(uint8=@uint8, ...
+                             uint16=@uint16, ...
+                             uint32=@uint32, ...
+                             uint64=@uint64, ...
+                             int8=@int8,...
+                             int16=@int16, ...
+                             int32=@int32, ... 
+                             int64=@int64, ...
+                             single=@single, ...
+                             double=@double);
+    end
+    
+
+    methods(Test)
+        function ErrorIfComplex(testCase, NumericType)
+            complexValue = NumericType(10 + 1i);
+            fcn = @() arrow.internal.validate.realnumeric(complexValue);
+            errID = "arrow:array:ComplexNumeric";
+            testCase.verifyError(fcn, errID);
+        end
+    end
+    
+end
\ No newline at end of file
diff --git a/matlab/test/arrow/internal/validate/tShape.m 
b/matlab/test/arrow/internal/validate/tShape.m
new file mode 100644
index 0000000000..52720a5e25
--- /dev/null
+++ b/matlab/test/arrow/internal/validate/tShape.m
@@ -0,0 +1,69 @@
+%TSHAPE Unit tests for arrow.internal.validate.shape.
+
+% Licensed to the Apache Software Foundation (ASF) under one or more
+% contributor license agreements.  See the NOTICE file distributed with
+% this work for additional information regarding copyright ownership.
+% The ASF licenses this file to you under the Apache License, Version
+% 2.0 (the "License"); you may not use this file except in compliance
+% with the License.  You may obtain a copy of the License at
+%
+%   http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS,
+% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+% implied.  See the License for the specific language governing
+% permissions and limitations under the License.
+
+classdef tShape < matlab.unittest.TestCase
+    
+    methods(Test)
+        function ErrorIf2DimensionalMatrix(testCase)
+            data = [1 2; 4 5];
+            fcn = @() arrow.internal.validate.shape(data);
+            errID = "arrow:array:InvalidShape";
+            testCase.verifyError(fcn, errID);
+        end
+
+        function ErrorIfNDMatrix(testCase)
+            data = ones([2 2 3]);
+            fcn = @() arrow.internal.validate.shape(data);
+            errID = "arrow:array:InvalidShape";
+            testCase.verifyError(fcn, errID);
+        end
+
+        function NoErrorIfRowVector(testCase)
+            data = [1 2 4 5];
+            fcn = @() arrow.internal.validate.shape(data);
+            testCase.verifyWarningFree(fcn);
+        end
+
+        function NoErrorIfColumnVector(testCase)
+            data = [1 2 4 5]';
+            fcn = @() arrow.internal.validate.shape(data);
+            testCase.verifyWarningFree(fcn);
+        end
+    
+        function NoErrorIfEmpty(testCase)
+            data = double.empty(0, 0);
+            fcn = @() arrow.internal.validate.shape(data);
+            testCase.verifyWarningFree(fcn);
+
+            data = double.empty(0, 1);
+            fcn = @() arrow.internal.validate.shape(data);
+            testCase.verifyWarningFree(fcn);
+
+            data = double.empty(1, 0);
+            fcn = @() arrow.internal.validate.shape(data);
+            testCase.verifyWarningFree(fcn);
+
+            data = double.empty(0, 1, 0);
+            fcn = @() arrow.internal.validate.shape(data);
+            testCase.verifyWarningFree(fcn);
+
+             data = double.empty(0, 0, 5);
+            fcn = @() arrow.internal.validate.shape(data);
+            testCase.verifyWarningFree(fcn);
+        end
+    end    
+end
\ No newline at end of file
diff --git a/matlab/src/matlab/+arrow/+array/Float32Array.m 
b/matlab/test/arrow/internal/validate/tType.m
similarity index 59%
copy from matlab/src/matlab/+arrow/+array/Float32Array.m
copy to matlab/test/arrow/internal/validate/tType.m
index c6be563d86..38ec58c3af 100644
--- a/matlab/src/matlab/+arrow/+array/Float32Array.m
+++ b/matlab/test/arrow/internal/validate/tType.m
@@ -1,3 +1,5 @@
+%TTYPE Unit tests for arrow.internal.validate.type.
+
 % Licensed to the Apache Software Foundation (ASF) under one or more
 % contributor license agreements.  See the NOTICE file distributed with
 % this work for additional information regarding copyright ownership.
@@ -13,21 +15,20 @@
 % implied.  See the License for the specific language governing
 % permissions and limitations under the License.
 
-classdef Float32Array < arrow.array.NumericArray
-% arrow.array.Float32Array
-
-    properties (Access=protected)
-        NullSubstitutionValue = single(NaN);
-    end
-
-    methods
-        function obj = Float32Array(data, varargin)
-            [email protected](data, "single", ...
-                "arrow.array.proxy.Float32Array", varargin{:});
+classdef tType < matlab.unittest.TestCase
+    
+    methods(Test)        
+        function ErrorIfWrongType(testCase)
+            data = uint64([1 2 3]);
+            fcn = @() arrow.internal.validate.type(data, "double");
+            errid = "arrow:array:InvalidType";
+            testCase.verifyError(fcn, errid);
         end
 
-        function data = single(obj)
-            data = obj.toMATLAB();
+        function NoErrorIfRightType(testCase)
+            data = uint64([1 2 3]);
+            fcn = @() arrow.internal.validate.type(data, "uint64");
+            testCase.verifyWarningFree(fcn);
         end
     end
-end
+end
\ No newline at end of file

Reply via email to