# Type::Tiny::Manual::UsingWithOther - using Type::Tiny with Class::Insid... - perldoc - [phpMan]

## NAME
    [Type::Tiny::Manual::UsingWithOther](https://www.chedong.com/phpMan.php/perldoc/Type%3A%3ATiny%3A%3AManual%3A%3AUsingWithOther/markdown) - using [Type::Tiny](https://www.chedong.com/phpMan.php/perldoc/Type%3A%3ATiny/markdown) with [Class::InsideOut](https://www.chedong.com/phpMan.php/perldoc/Class%3A%3AInsideOut/markdown), [Params::Check](https://www.chedong.com/phpMan.php/perldoc/Params%3A%3ACheck/markdown), and
    [Object::Accessor](https://www.chedong.com/phpMan.php/perldoc/Object%3A%3AAccessor/markdown).

## MANUAL
    The antlers crew aren't the only object-oriented programming toolkits in Perl town. Although
    [Type::Tiny](https://www.chedong.com/phpMan.php/perldoc/Type%3A%3ATiny/markdown) might have been built with Moose, Mouse, and Moo in mind, it can be used with other
    toolkits.

    These toolkits are... well... hmm... okay... they exist.

    If you are starting a new project, there's very little reason not to use [Class::Tiny](https://www.chedong.com/phpMan.php/perldoc/Class%3A%3ATiny/markdown), Moo, or
    Moose. So you're probably okay to skip this part of the fine manual and go straight to
    [Type::Tiny::Manual::UsingWithTestMore](https://www.chedong.com/phpMan.php/perldoc/Type%3A%3ATiny%3A%3AManual%3A%3AUsingWithTestMore/markdown).

### [Class::InsideOut](https://www.chedong.com/phpMan.php/perldoc/Class%3A%3AInsideOut/markdown)
    You want [Class::InsideOut](https://www.chedong.com/phpMan.php/perldoc/Class%3A%3AInsideOut/markdown) 1.13 or above, which has support for blessed and overloaded objects
    (including [Type::Tiny](https://www.chedong.com/phpMan.php/perldoc/Type%3A%3ATiny/markdown) type constraints) for the "get_hook" and "set_hook" options.

      package Person {
        use [Class::InsideOut](https://www.chedong.com/phpMan.php/perldoc/Class%3A%3AInsideOut/markdown) qw( public );
        use [Types::Standard](https://www.chedong.com/phpMan.php/perldoc/Types%3A%3AStandard/markdown) qw( Str Int );
        use [Types::Common::Numeric](https://www.chedong.com/phpMan.php/perldoc/Types%3A%3ACommon%3A%3ANumeric/markdown) qw( PositiveInt );
        use [Type::Params](https://www.chedong.com/phpMan.php/perldoc/Type%3A%3AParams/markdown) qw( signature );

        # Type checks are really easy.
        # Just supply the type as a set hook.
        public name => my %_name, {
          set_hook => Str,
        };

        # Define a type that silently coerces negative values
        # to positive. It's silly, but it works as an example!
        my $Years = PositiveInt->plus_coercions(Int, q{ abs($_) });

        # Coercions are more annoying, but possible.
        public age => my %_age, {
          set_hook => sub { $_ = $Years->assert_coerce($_) },
        };

        # Parameter checking for methods is as expected.
        sub get_older {
          state $check = signature( method => 1, positional => [ $Years ] );
          my ( $self, $years ) = $check->( @_ );
          $self->_set_age( $self->age + $years );
        }
      }

### [Params::Check](https://www.chedong.com/phpMan.php/perldoc/Params%3A%3ACheck/markdown) and [Object::Accessor](https://www.chedong.com/phpMan.php/perldoc/Object%3A%3AAccessor/markdown)
    The [Params::Check](https://www.chedong.com/phpMan.php/perldoc/Params%3A%3ACheck/markdown) allow() function, the "allow" option for the [Params::Check](https://www.chedong.com/phpMan.php/perldoc/Params%3A%3ACheck/markdown) check() function,
    and the input validation mechanism for [Object::Accessor](https://www.chedong.com/phpMan.php/perldoc/Object%3A%3AAccessor/markdown) all work in the same way, which is
    basically a limited pure-Perl implementation of the smart match operator. While this doesn't
    directly support [Type::Tiny](https://www.chedong.com/phpMan.php/perldoc/Type%3A%3ATiny/markdown) constraints, it does support coderefs. You can use [Type::Tiny](https://www.chedong.com/phpMan.php/perldoc/Type%3A%3ATiny/markdown)'s
    "compiled_check" method to obtain a suitable coderef.

    [Param::Check](https://www.chedong.com/phpMan.php/perldoc/Param%3A%3ACheck/markdown) example:

      my $tmpl = {
        name => { allow => Str->compiled_check },
        age  => { allow => Int->compiled_check },
      };
      check($tmpl, { name => "Bob", age => 32 })
        or die [Params::Check::last_error](https://www.chedong.com/phpMan.php/perldoc/Params%3A%3ACheck%3A%3Alasterror/markdown)();

    [Object::Accessor](https://www.chedong.com/phpMan.php/perldoc/Object%3A%3AAccessor/markdown) example:

      my $obj = [Object::Accessor](https://www.chedong.com/phpMan.php/perldoc/Object%3A%3AAccessor/markdown)->new;
      $obj->mk_accessors(
        { name => Str->compiled_check },
        { age  => Int->compiled_check },
      );

    *Caveat:* [Object::Accessor](https://www.chedong.com/phpMan.php/perldoc/Object%3A%3AAccessor/markdown) doesn't die when a value fails to meet its type constraint; instead
    it outputs a warning to STDERR. This behaviour can be changed by setting
    "$[Object::Accessor::FATAL](https://www.chedong.com/phpMan.php/perldoc/Object%3A%3AAccessor%3A%3AFATAL/markdown) = 1".

### [Class::Struct](https://www.chedong.com/phpMan.php/perldoc/Class%3A%3AStruct/markdown)
    This is proof-of-concept of how [Type::Tiny](https://www.chedong.com/phpMan.php/perldoc/Type%3A%3ATiny/markdown) can be used to constrain attributes for
    [Class::Struct](https://www.chedong.com/phpMan.php/perldoc/Class%3A%3AStruct/markdown). It's probably not a good idea to use this in production as it slows down
    "[UNIVERSAL::isa](https://www.chedong.com/phpMan.php/perldoc/UNIVERSAL%3A%3Aisa/markdown)" globally.

      use [Types::Standard](https://www.chedong.com/phpMan.php/perldoc/Types%3A%3AStandard/markdown) -types;
      use [Class::Struct](https://www.chedong.com/phpMan.php/perldoc/Class%3A%3AStruct/markdown);

      {
        my %MAP;
        my $orig_isa = \&[UNIVERSAL::isa](https://www.chedong.com/phpMan.php/perldoc/UNIVERSAL%3A%3Aisa/markdown);
        *[UNIVERSAL::isa](https://www.chedong.com/phpMan.php/perldoc/UNIVERSAL%3A%3Aisa/markdown) = sub {
          return $MAP{$1}->check($_[0])
            if $_[1] =~ /^[CLASSSTRUCT::TYPETINY](https://www.chedong.com/phpMan.php/perldoc/CLASSSTRUCT%3A%3ATYPETINY/markdown)::(.+)$/ && exists $MAP{$1};
          goto $orig;
        };
        my $orig_dn = \&[Type::Tiny::display_name](https://www.chedong.com/phpMan.php/perldoc/Type%3A%3ATiny%3A%3Adisplayname/markdown);
        *[Type::Tiny::display_name](https://www.chedong.com/phpMan.php/perldoc/Type%3A%3ATiny%3A%3Adisplayname/markdown) = sub {
          if ([caller(1)](https://www.chedong.com/phpMan.php/man/caller/1/markdown) eq '[Class::Struct](https://www.chedong.com/phpMan.php/perldoc/Class%3A%3AStruct/markdown)') {
            $MAP{$_[0]{uniq}} = $_[0];
            return "[CLASSSTRUCT::TYPETINY](https://www.chedong.com/phpMan.php/perldoc/CLASSSTRUCT%3A%3ATYPETINY/markdown)::".$_[0]{uniq};
          }
          goto $orig_dn;
        };
      }

      struct Person => [ name => Str, age => Int ];

      my $bob = Person->new(
        name => "Bob",
        age  => 21,
      );

      $bob->name("Robert");   # okay
      $bob->name([]);         # dies

### [Class::Plain](https://www.chedong.com/phpMan.php/perldoc/Class%3A%3APlain/markdown)
    There is not currently a high level of integration, but here's a quick example of type checking
    attributes in the constructor.

    If any of your accessors are ":rw" then you would also need to add type checks to those.

      use [Class::Plain](https://www.chedong.com/phpMan.php/perldoc/Class%3A%3APlain/markdown);

      class Point {
        use [Types::Common](https://www.chedong.com/phpMan.php/perldoc/Types%3A%3ACommon/markdown) -types, -sigs;

        field x :reader;
        field y :reader;

        signature_for new => (
          method => !!1,
          bless  => !!0,
          named  => [
            x => Int,
            y => Int,
          ],
        );

        method as_arrayref () {
          return [ $self->x, $self->y ];
        }
      }

    The following signature may also be of interest:

      signature_for new => (
        method   => !!1,
        multiple => [
          {
            named => [
              x => Int,
              y => Int,
            ],
            bless => !!0,
          },
          {
            positional => [ Int, Int ],
            goto_next  => sub {
              my ( $class, $x, $y ) = @_;
              return ( $class, { x => $x, y => $y } ),
            },
          },
        ],
      );

    This would allow your class to be instantiated using any of the following:

      my $point11 = Point->new( { x => 1, y => 1 } );
      my $point22 = Point->new(   x => 2, y => 2   );
      my $point33 = Point->new( 3, 3 );

## NEXT STEPS
    Here's your next step:

    *   [Type::Tiny::Manual::UsingWithTestMore](https://www.chedong.com/phpMan.php/perldoc/Type%3A%3ATiny%3A%3AManual%3A%3AUsingWithTestMore/markdown)

        [Type::Tiny](https://www.chedong.com/phpMan.php/perldoc/Type%3A%3ATiny/markdown) for test suites.

## AUTHOR
    Toby Inkster <<tobyink@cpan.org>>.

## COPYRIGHT AND LICENCE
    This software is copyright (c) 2013-2014, 2017-2023 by Toby Inkster.

    This is free software; you can redistribute it and/or modify it under the same terms as the Perl
    5 programming language system itself.

## DISCLAIMER OF WARRANTIES
    THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
    WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
    PURPOSE.

